<div class="tutorial-bundle" data-metadata-json='{"difficulty": "advanced", "groupedProjectAssets": [{"name": "QBert character", "assets": ["qbert0.png", "qbert1.png", "qbert2.png", "qbert3.png"]}, {"name": "blocks", "assets": ["block-lit.png", "block-unlit.png"]}]}' data-tip-sha1="beb03493c2130e154530692c4ed4b1e009c9eb39"><div class="front-matter" data-complete-code-text="# Turn all the blocks yellow by jumping with the arrow keys,
# but don't fall off the pyramid!

import pytch


blocks_left = 0


class Background(pytch.Stage):
    Backdrops = [&quot;background.png&quot;]


class LevelClearedText(pytch.Sprite):
    Costumes = [&quot;level-cleared-text.png&quot;]
    Sounds = [&quot;fanfare.mp3&quot;]

    @pytch.when_green_flag_clicked
    def start_hidden(self):
        self.hide()

    @pytch.when_I_receive(&quot;level-cleared&quot;)
    def congratulate_player(self):
        self.go_to_xy(-150, 80)
        self.show()
        self.start_sound(&quot;fanfare&quot;)


class Block(pytch.Sprite):
    Costumes = [&quot;block-unlit.png&quot;, &quot;block-lit.png&quot;]
    Sounds = [&quot;pop.mp3&quot;, &quot;bell-ping.mp3&quot;]

    @pytch.when_green_flag_clicked
    def create_pyramid(self):
        for r in range(7):
            for b in range(7 - r):
                block_x = -150 + (b * 56) + (r * 28)
                block_y = -145 + (r * 42)
                self.go_to_xy(block_x, block_y)
                self.pyramid_r = r
                self.pyramid_b = b
                pytch.create_clone_of(self)
        self.hide()
        self.pyramid_r = -1
        self.pyramid_b = -1
        pytch.broadcast(&quot;set-up-qbert&quot;)

    @pytch.when_I_receive(&quot;check-block&quot;)
    def check_whether_landed_on(self):
        qbert_r, qbert_b = Qbert.the_original().pyramid_coordinates()
        if self.pyramid_r == qbert_r and self.pyramid_b == qbert_b:
            if self.costume_name == &quot;block-unlit&quot;:
                self.start_sound(&quot;bell-ping&quot;)
                self.switch_costume(&quot;block-lit&quot;)
                global blocks_left
                blocks_left -= 1
                if blocks_left == 0:
                    pytch.broadcast(&quot;level-cleared&quot;)
            else:
                self.start_sound(&quot;pop&quot;)


class Qbert(pytch.Sprite):
    Costumes = [&quot;qbert0.png&quot;, &quot;qbert1.png&quot;, &quot;qbert2.png&quot;, &quot;qbert3.png&quot;]

    @pytch.when_green_flag_clicked
    def start_hidden(self):
        self.hide()

    # This list must have exactly 14 entries.
    bounce = [6, 4, 2, 1, 0, 0, 0, 0, 0, 0, -1, -2, -4, -6]

    @pytch.when_I_receive(&quot;set-up-qbert&quot;)
    def go_to_starting_position(self):
        self.go_to_xy(-150 + 3 * 56, -145 + (6 * 42) + 28)
        self.switch_costume(&quot;qbert1&quot;)
        self.go_to_front_layer()
        self.show()
        self.jumping = False
        global blocks_left
        blocks_left = len(Block.all_clones())

    def pyramid_coordinates(self):
        y_on_stage = self.y_position
        pyramid_r = (y_on_stage + 145 - 28) / 42
        x_on_stage = self.x_position
        pyramid_b = (x_on_stage + 150 - pyramid_r * 28) / 56
        return (pyramid_r, pyramid_b)

    def jump(self, x_speed, y_speed, costume):
        if self.jumping:
            return
        self.jumping = True
        self.switch_costume(costume)
        for frame in range(14):
            self.change_x(x_speed)
            self.change_y(y_speed + self.bounce[frame])

        r, b = self.pyramid_coordinates()
        if r &lt; 0 or r &gt;= 7 or b &lt; 0 or b &gt;= (7 - r):
            pytch.broadcast(&quot;fall-off&quot;)
        else:
            pytch.broadcast_and_wait(&quot;check-block&quot;)
            self.jumping = False

    @pytch.when_I_receive(&quot;fall-off&quot;)
    def disappear(self):
        for i in range(100, 10, -5):
            self.set_size(i / 100.0)
        self.hide()

    @pytch.when_key_pressed(&quot;ArrowUp&quot;)
    def jump_up(self):
        self.jump(2, 3, &quot;qbert0&quot;)

    @pytch.when_key_pressed(&quot;ArrowDown&quot;)
    def jump_down(self):
        self.jump(-2, -3, &quot;qbert2&quot;)

    @pytch.when_key_pressed(&quot;ArrowLeft&quot;)
    def jump_left(self):
        self.jump(-2, 3, &quot;qbert3&quot;)

    @pytch.when_key_pressed(&quot;ArrowRight&quot;)
    def jump_right(self):
        self.jump(2, -3, &quot;qbert1&quot;)
" data-initial-code-text="import pytch
"><h1>Q*bert: Recreate the cube-hopping action</h1><p>As Mark Vanstone explains in <a href="https://wireframe.raspberrypi.org/issues/42">Issue 42 of Wireframe
magazine</a>:</p><blockquote>
<p>Late in 1982, a funny little orange character with a big nose landed
in arcades.  The titular Q*bert’s task was to jump around a network of
cubes arranged in a pyramid formation, changing the colours of each as
they went.  Once the cubes were all the same colour, it was on to the
next level.</p>
</blockquote><p>In this tutorial we'll follow Mark's example and create the basics of
this classic arcade game.</p></div><div class="chapter-content"><h2>Set up the background</h2><p>Our first job is to set up the playing background.  We'll use the
image from Wireframe, modified slightly to fit the size of the Pytch
stage.  The image is bundled with this tutorial, so we just need to
define the sort of <em>Stage</em> we will be using in this game:</p><div class="patch-container" data-code-as-of-commit='import pytch


class Background(pytch.Stage):
    Backdrops = ["background.png"]
' data-slug="add-Stage-with-backdrop"><div class="patch"><table><tbody class="diff-unch"><tr><td class="linenum"><pre>1</pre></td><td class="linenum"><pre>1</pre></td><td><pre>import pytch</pre></td></tr></tbody><tbody class="diff-add" data-added-text='

class Background(pytch.Stage):
    Backdrops = ["background.png"]
'><tr><td class="linenum"></td><td class="linenum"><pre>2</pre></td><td><pre></pre></td></tr><tr><td class="linenum"></td><td class="linenum"><pre>3</pre></td><td><pre></pre></td></tr><tr><td class="linenum"></td><td class="linenum"><pre>4</pre></td><td><pre>class Background(pytch.Stage):</pre></td></tr><tr><td class="linenum"></td><td class="linenum"><pre>5</pre></td><td><pre>    Backdrops = ["background.png"]</pre></td></tr></tbody></table></div></div><p>If you run the project now, by clicking the <em>green flag</em>, you'll see
the background.</p></div><div class="chapter-content"><h2>Define the blocks for making the pyramid</h2><p>The game world is a pyramid of blocks.  We'll make this in Pytch by
having a <code>Block</code> sprite, and create a <em>clone</em> of it for every block in
the pyramid.  First we'll define the <code>Block</code> sprite, and say what
costumes we'll use with it.  The two costumes have different coloured
tops, one for the starting state, and one which is lit up once Qbert
has landed on that cube.</p><div class="patch-container" data-code-as-of-commit='import pytch


class Background(pytch.Stage):
    Backdrops = ["background.png"]


class Block(pytch.Sprite):
    Costumes = ["block-unlit.png", "block-lit.png"]
' data-slug="add-Block-with-costumes"><div class="patch"><table><tbody class="diff-unch"><tr><td class="linenum"><pre>3</pre></td><td class="linenum"><pre>3</pre></td><td><pre></pre></td></tr><tr><td class="linenum"><pre>4</pre></td><td class="linenum"><pre>4</pre></td><td><pre>class Background(pytch.Stage):</pre></td></tr><tr><td class="linenum"><pre>5</pre></td><td class="linenum"><pre>5</pre></td><td><pre>    Backdrops = ["background.png"]</pre></td></tr></tbody><tbody class="diff-add" data-added-text='

class Block(pytch.Sprite):
    Costumes = ["block-unlit.png", "block-lit.png"]
'><tr><td class="linenum"></td><td class="linenum"><pre>6</pre></td><td><pre></pre></td></tr><tr><td class="linenum"></td><td class="linenum"><pre>7</pre></td><td><pre></pre></td></tr><tr><td class="linenum"></td><td class="linenum"><pre>8</pre></td><td><pre>class Block(pytch.Sprite):</pre></td></tr><tr><td class="linenum"></td><td class="linenum"><pre>9</pre></td><td><pre>    Costumes = ["block-unlit.png", "block-lit.png"]</pre></td></tr></tbody></table></div></div><p>If you try the project now (click the green flag), you can see a
single block appear in the middle of the stage.  Our next job will be
to arrange lots of <em>clones</em> of this block into a pyramid.</p></div><div class="chapter-content"><h2>Make the pyramid</h2><p>Getting this right is going to require some maths!  The pyramid has
seven <em>rows</em>, and each row has a different number of <em>blocks</em> in it.
Each block will be a clone of the original <em>Block</em> sprite.</p><p>We'll give each row and block a number.  The bottom row will be <em>row
zero</em>, and within each row, the block at the far left will be <em>block
zero</em> of that row.</p><p>The bottom row (row 0, remember) has seven blocks in it.  The next row
up (row 1) has six blocks, and so on.  We can see that row number <em>r</em>
has (7 − <em>r</em>) blocks in it.</p><p>To work out where to put each block, we need to work out its <em>x</em> and
<em>y</em> coordinates.</p><p>**
TODO: Finish this explanation, possibly with the aid of a picture.
**</p><p>Putting this altogether, we can create our clones with this code:</p><div class="patch-container" data-code-as-of-commit='import pytch


class Background(pytch.Stage):
    Backdrops = ["background.png"]


class Block(pytch.Sprite):
    Costumes = ["block-unlit.png", "block-lit.png"]

    @pytch.when_green_flag_clicked
    def create_pyramid(self):
        for r in range(7):
            for b in range(7 - r):
                block_x = -150 + (b * 56) + (r * 28)
                block_y = -145 + (r * 42)
                self.go_to_xy(block_x, block_y)
                pytch.create_clone_of(self)
' data-slug="create-block-pyramid"><div class="patch"><table><tbody class="diff-unch"><tr><td class="linenum"><pre>7</pre></td><td class="linenum"><pre>7</pre></td><td><pre></pre></td></tr><tr><td class="linenum"><pre>8</pre></td><td class="linenum"><pre>8</pre></td><td><pre>class Block(pytch.Sprite):</pre></td></tr><tr><td class="linenum"><pre>9</pre></td><td class="linenum"><pre>9</pre></td><td><pre>    Costumes = ["block-unlit.png", "block-lit.png"]</pre></td></tr></tbody><tbody class="diff-add" data-added-text="
    @pytch.when_green_flag_clicked
    def create_pyramid(self):
        for r in range(7):
            for b in range(7 - r):
                block_x = -150 + (b * 56) + (r * 28)
                block_y = -145 + (r * 42)
                self.go_to_xy(block_x, block_y)
                pytch.create_clone_of(self)
"><tr><td class="linenum"></td><td class="linenum"><pre>10</pre></td><td><pre></pre></td></tr><tr><td class="linenum"></td><td class="linenum"><pre>11</pre></td><td><pre>    @pytch.when_green_flag_clicked</pre></td></tr><tr><td class="linenum"></td><td class="linenum"><pre>12</pre></td><td><pre>    def create_pyramid(self):</pre></td></tr><tr><td class="linenum"></td><td class="linenum"><pre>13</pre></td><td><pre>        for r in range(7):</pre></td></tr><tr><td class="linenum"></td><td class="linenum"><pre>14</pre></td><td><pre>            for b in range(7 - r):</pre></td></tr><tr><td class="linenum"></td><td class="linenum"><pre>15</pre></td><td><pre>                block_x = -150 + (b * 56) + (r * 28)</pre></td></tr><tr><td class="linenum"></td><td class="linenum"><pre>16</pre></td><td><pre>                block_y = -145 + (r * 42)</pre></td></tr><tr><td class="linenum"></td><td class="linenum"><pre>17</pre></td><td><pre>                self.go_to_xy(block_x, block_y)</pre></td></tr><tr><td class="linenum"></td><td class="linenum"><pre>18</pre></td><td><pre>                pytch.create_clone_of(self)</pre></td></tr></tbody></table></div></div><p>If you green-flag the project now, you'll see the pyramid appear block
by block.</p><p>One tiny detail is that the <em>original</em> <code>Block</code> sprite is still there,
and this will complicate things.  We'll work round this by hiding the
original once all the clones have been made:</p><div class="patch-container" data-code-as-of-commit='import pytch


class Background(pytch.Stage):
    Backdrops = ["background.png"]


class Block(pytch.Sprite):
    Costumes = ["block-unlit.png", "block-lit.png"]

    @pytch.when_green_flag_clicked
    def create_pyramid(self):
        for r in range(7):
            for b in range(7 - r):
                block_x = -150 + (b * 56) + (r * 28)
                block_y = -145 + (r * 42)
                self.go_to_xy(block_x, block_y)
                pytch.create_clone_of(self)
        self.hide()
' data-slug="hide-original-block"><div class="patch"><table><tbody class="diff-unch"><tr><td class="linenum"><pre>16</pre></td><td class="linenum"><pre>16</pre></td><td><pre>                block_y = -145 + (r * 42)</pre></td></tr><tr><td class="linenum"><pre>17</pre></td><td class="linenum"><pre>17</pre></td><td><pre>                self.go_to_xy(block_x, block_y)</pre></td></tr><tr><td class="linenum"><pre>18</pre></td><td class="linenum"><pre>18</pre></td><td><pre>                pytch.create_clone_of(self)</pre></td></tr></tbody><tbody class="diff-add" data-added-text="        self.hide()
"><tr><td class="linenum"></td><td class="linenum"><pre>19</pre></td><td><pre>        self.hide()</pre></td></tr></tbody></table></div></div></div><div class="chapter-content"><h2>Introduce the Q*bert character</h2><p>Now let's bring in our hero!  We'll define a <em>Sprite</em> for Q*bert:</p><div class="patch-container" data-code-as-of-commit='import pytch


class Background(pytch.Stage):
    Backdrops = ["background.png"]


class Block(pytch.Sprite):
    Costumes = ["block-unlit.png", "block-lit.png"]

    @pytch.when_green_flag_clicked
    def create_pyramid(self):
        for r in range(7):
            for b in range(7 - r):
                block_x = -150 + (b * 56) + (r * 28)
                block_y = -145 + (r * 42)
                self.go_to_xy(block_x, block_y)
                pytch.create_clone_of(self)
        self.hide()


class Qbert(pytch.Sprite):
    Costumes = ["qbert0.png", "qbert1.png", "qbert2.png", "qbert3.png"]
' data-slug="add-Qbert-with-costumes"><div class="patch"><table><tbody class="diff-unch"><tr><td class="linenum"><pre>17</pre></td><td class="linenum"><pre>17</pre></td><td><pre>                self.go_to_xy(block_x, block_y)</pre></td></tr><tr><td class="linenum"><pre>18</pre></td><td class="linenum"><pre>18</pre></td><td><pre>                pytch.create_clone_of(self)</pre></td></tr><tr><td class="linenum"><pre>19</pre></td><td class="linenum"><pre>19</pre></td><td><pre>        self.hide()</pre></td></tr></tbody><tbody class="diff-add" data-added-text='

class Qbert(pytch.Sprite):
    Costumes = ["qbert0.png", "qbert1.png", "qbert2.png", "qbert3.png"]
'><tr><td class="linenum"></td><td class="linenum"><pre>20</pre></td><td><pre></pre></td></tr><tr><td class="linenum"></td><td class="linenum"><pre>21</pre></td><td><pre></pre></td></tr><tr><td class="linenum"></td><td class="linenum"><pre>22</pre></td><td><pre>class Qbert(pytch.Sprite):</pre></td></tr><tr><td class="linenum"></td><td class="linenum"><pre>23</pre></td><td><pre>    Costumes = ["qbert0.png", "qbert1.png", "qbert2.png", "qbert3.png"]</pre></td></tr></tbody></table></div></div><p>Q*bert has four costumes, one for each direction they might face.</p><p>If you run the program now, Q*bert will straight away appear in the
middle of the stage, in an odd place as the pyramid gets built
underneath.  We'll tell Q*bert to hide as soon as the game starts:</p><div class="patch-container" data-code-as-of-commit='import pytch


class Background(pytch.Stage):
    Backdrops = ["background.png"]


class Block(pytch.Sprite):
    Costumes = ["block-unlit.png", "block-lit.png"]

    @pytch.when_green_flag_clicked
    def create_pyramid(self):
        for r in range(7):
            for b in range(7 - r):
                block_x = -150 + (b * 56) + (r * 28)
                block_y = -145 + (r * 42)
                self.go_to_xy(block_x, block_y)
                pytch.create_clone_of(self)
        self.hide()


class Qbert(pytch.Sprite):
    Costumes = ["qbert0.png", "qbert1.png", "qbert2.png", "qbert3.png"]

    @pytch.when_green_flag_clicked
    def start_hidden(self):
        self.hide()
' data-slug="start-Qbert-not-shown"><div class="patch"><table><tbody class="diff-unch"><tr><td class="linenum"><pre>21</pre></td><td class="linenum"><pre>21</pre></td><td><pre></pre></td></tr><tr><td class="linenum"><pre>22</pre></td><td class="linenum"><pre>22</pre></td><td><pre>class Qbert(pytch.Sprite):</pre></td></tr><tr><td class="linenum"><pre>23</pre></td><td class="linenum"><pre>23</pre></td><td><pre>    Costumes = ["qbert0.png", "qbert1.png", "qbert2.png", "qbert3.png"]</pre></td></tr></tbody><tbody class="diff-add" data-added-text="
    @pytch.when_green_flag_clicked
    def start_hidden(self):
        self.hide()
"><tr><td class="linenum"></td><td class="linenum"><pre>24</pre></td><td><pre></pre></td></tr><tr><td class="linenum"></td><td class="linenum"><pre>25</pre></td><td><pre>    @pytch.when_green_flag_clicked</pre></td></tr><tr><td class="linenum"></td><td class="linenum"><pre>26</pre></td><td><pre>    def start_hidden(self):</pre></td></tr><tr><td class="linenum"></td><td class="linenum"><pre>27</pre></td><td><pre>        self.hide()</pre></td></tr></tbody></table></div></div><p>We'll want Q*bert to set themselves up once the pyramid is complete,
so we'll define a method which will listen out for a <code>"set-up-qbert"</code>
message.  This method will make Q*bert move to the top block, face
downhill, and show themselves:</p><p>**
TODO: Explain extra offset of 28.
**</p><div class="patch-container" data-code-as-of-commit='import pytch


class Background(pytch.Stage):
    Backdrops = ["background.png"]


class Block(pytch.Sprite):
    Costumes = ["block-unlit.png", "block-lit.png"]

    @pytch.when_green_flag_clicked
    def create_pyramid(self):
        for r in range(7):
            for b in range(7 - r):
                block_x = -150 + (b * 56) + (r * 28)
                block_y = -145 + (r * 42)
                self.go_to_xy(block_x, block_y)
                pytch.create_clone_of(self)
        self.hide()


class Qbert(pytch.Sprite):
    Costumes = ["qbert0.png", "qbert1.png", "qbert2.png", "qbert3.png"]

    @pytch.when_green_flag_clicked
    def start_hidden(self):
        self.hide()

    @pytch.when_I_receive("set-up-qbert")
    def go_to_starting_position(self):
        self.go_to_xy(-150 + 3 * 56, -145 + (6 * 42) + 28)
        self.switch_costume("qbert1")
        self.show()
' data-slug="initialise-Qbert-position"><div class="patch"><table><tbody class="diff-unch"><tr><td class="linenum"><pre>25</pre></td><td class="linenum"><pre>25</pre></td><td><pre>    @pytch.when_green_flag_clicked</pre></td></tr><tr><td class="linenum"><pre>26</pre></td><td class="linenum"><pre>26</pre></td><td><pre>    def start_hidden(self):</pre></td></tr><tr><td class="linenum"><pre>27</pre></td><td class="linenum"><pre>27</pre></td><td><pre>        self.hide()</pre></td></tr></tbody><tbody class="diff-add" data-added-text='
    @pytch.when_I_receive("set-up-qbert")
    def go_to_starting_position(self):
        self.go_to_xy(-150 + 3 * 56, -145 + (6 * 42) + 28)
        self.switch_costume("qbert1")
        self.show()
'><tr><td class="linenum"></td><td class="linenum"><pre>28</pre></td><td><pre></pre></td></tr><tr><td class="linenum"></td><td class="linenum"><pre>29</pre></td><td><pre>    @pytch.when_I_receive("set-up-qbert")</pre></td></tr><tr><td class="linenum"></td><td class="linenum"><pre>30</pre></td><td><pre>    def go_to_starting_position(self):</pre></td></tr><tr><td class="linenum"></td><td class="linenum"><pre>31</pre></td><td><pre>        self.go_to_xy(-150 + 3 * 56, -145 + (6 * 42) + 28)</pre></td></tr><tr><td class="linenum"></td><td class="linenum"><pre>32</pre></td><td><pre>        self.switch_costume("qbert1")</pre></td></tr><tr><td class="linenum"></td><td class="linenum"><pre>33</pre></td><td><pre>        self.show()</pre></td></tr></tbody></table></div></div><p>This should happen once the pyramid is ready for Q*bert, so we'll go
back to the <em>Block</em> sprite and send the <code>"set-up-qbert"</code> message once
we've created all the clones:</p><div class="patch-container" data-code-as-of-commit='import pytch


class Background(pytch.Stage):
    Backdrops = ["background.png"]


class Block(pytch.Sprite):
    Costumes = ["block-unlit.png", "block-lit.png"]

    @pytch.when_green_flag_clicked
    def create_pyramid(self):
        for r in range(7):
            for b in range(7 - r):
                block_x = -150 + (b * 56) + (r * 28)
                block_y = -145 + (r * 42)
                self.go_to_xy(block_x, block_y)
                pytch.create_clone_of(self)
        self.hide()
        pytch.broadcast("set-up-qbert")


class Qbert(pytch.Sprite):
    Costumes = ["qbert0.png", "qbert1.png", "qbert2.png", "qbert3.png"]

    @pytch.when_green_flag_clicked
    def start_hidden(self):
        self.hide()

    @pytch.when_I_receive("set-up-qbert")
    def go_to_starting_position(self):
        self.go_to_xy(-150 + 3 * 56, -145 + (6 * 42) + 28)
        self.switch_costume("qbert1")
        self.show()
' data-slug="tell-Qbert-to-set-up"><div class="patch"><table><tbody class="diff-unch"><tr><td class="linenum"><pre>17</pre></td><td class="linenum"><pre>17</pre></td><td><pre>                self.go_to_xy(block_x, block_y)</pre></td></tr><tr><td class="linenum"><pre>18</pre></td><td class="linenum"><pre>18</pre></td><td><pre>                pytch.create_clone_of(self)</pre></td></tr><tr><td class="linenum"><pre>19</pre></td><td class="linenum"><pre>19</pre></td><td><pre>        self.hide()</pre></td></tr></tbody><tbody class="diff-add" data-added-text='        pytch.broadcast("set-up-qbert")
'><tr><td class="linenum"></td><td class="linenum"><pre>20</pre></td><td><pre>        pytch.broadcast("set-up-qbert")</pre></td></tr></tbody><tbody class="diff-unch"><tr><td class="linenum"><pre>20</pre></td><td class="linenum"><pre>21</pre></td><td><pre></pre></td></tr><tr><td class="linenum"><pre>21</pre></td><td class="linenum"><pre>22</pre></td><td><pre></pre></td></tr><tr><td class="linenum"><pre>22</pre></td><td class="linenum"><pre>23</pre></td><td><pre>class Qbert(pytch.Sprite):</pre></td></tr></tbody></table></div></div><p>There's another detail we should make sure is right.  Q*bert needs to
appear "in front of" the pyramid of blocks.  More or less by chance,
this is what happens at the moment, but it's a good idea to make sure,
in case we rearrange our code later.  So we'll bring Q*bert to the
<em>front</em> of the drawing:</p><div class="patch-container" data-code-as-of-commit='import pytch


class Background(pytch.Stage):
    Backdrops = ["background.png"]


class Block(pytch.Sprite):
    Costumes = ["block-unlit.png", "block-lit.png"]

    @pytch.when_green_flag_clicked
    def create_pyramid(self):
        for r in range(7):
            for b in range(7 - r):
                block_x = -150 + (b * 56) + (r * 28)
                block_y = -145 + (r * 42)
                self.go_to_xy(block_x, block_y)
                pytch.create_clone_of(self)
        self.hide()
        pytch.broadcast("set-up-qbert")


class Qbert(pytch.Sprite):
    Costumes = ["qbert0.png", "qbert1.png", "qbert2.png", "qbert3.png"]

    @pytch.when_green_flag_clicked
    def start_hidden(self):
        self.hide()

    @pytch.when_I_receive("set-up-qbert")
    def go_to_starting_position(self):
        self.go_to_xy(-150 + 3 * 56, -145 + (6 * 42) + 28)
        self.switch_costume("qbert1")
        self.go_to_front_layer()
        self.show()
' data-slug="move-Qbert-to-front"><div class="patch"><table><tbody class="diff-unch"><tr><td class="linenum"><pre>31</pre></td><td class="linenum"><pre>31</pre></td><td><pre>    def go_to_starting_position(self):</pre></td></tr><tr><td class="linenum"><pre>32</pre></td><td class="linenum"><pre>32</pre></td><td><pre>        self.go_to_xy(-150 + 3 * 56, -145 + (6 * 42) + 28)</pre></td></tr><tr><td class="linenum"><pre>33</pre></td><td class="linenum"><pre>33</pre></td><td><pre>        self.switch_costume("qbert1")</pre></td></tr></tbody><tbody class="diff-add" data-added-text="        self.go_to_front_layer()
"><tr><td class="linenum"></td><td class="linenum"><pre>34</pre></td><td><pre>        self.go_to_front_layer()</pre></td></tr></tbody><tbody class="diff-unch"><tr><td class="linenum"><pre>34</pre></td><td class="linenum"><pre>35</pre></td><td><pre>        self.show()</pre></td></tr></tbody></table></div></div></div><div class="chapter-content"><h2>Let the player move Q*bert</h2><p>The player will control Q*bert with the arrow keys.  We'll start with
the <em>down</em> arrow key, which will move Q*bert 'southwest' on the
screen.</p><p>We want Q*bert to face in the correct direction.  We can check in the
<em>Images and sounds</em> tab to see which image this is — it's <code>"qbert2"</code>.
We want Q*bert to move 28 pixels to the left and 42 pixels down, which
we'll do in 14 steps of "2 left, 3 down" to make the movement smoother.</p><div class="patch-container" data-code-as-of-commit='import pytch


class Background(pytch.Stage):
    Backdrops = ["background.png"]


class Block(pytch.Sprite):
    Costumes = ["block-unlit.png", "block-lit.png"]

    @pytch.when_green_flag_clicked
    def create_pyramid(self):
        for r in range(7):
            for b in range(7 - r):
                block_x = -150 + (b * 56) + (r * 28)
                block_y = -145 + (r * 42)
                self.go_to_xy(block_x, block_y)
                pytch.create_clone_of(self)
        self.hide()
        pytch.broadcast("set-up-qbert")


class Qbert(pytch.Sprite):
    Costumes = ["qbert0.png", "qbert1.png", "qbert2.png", "qbert3.png"]

    @pytch.when_green_flag_clicked
    def start_hidden(self):
        self.hide()

    @pytch.when_I_receive("set-up-qbert")
    def go_to_starting_position(self):
        self.go_to_xy(-150 + 3 * 56, -145 + (6 * 42) + 28)
        self.switch_costume("qbert1")
        self.go_to_front_layer()
        self.show()

    @pytch.when_key_pressed("ArrowDown")
    def jump_down(self):
        self.switch_costume("qbert2")
        for frame in range(14):
            self.change_x(-2)
            self.change_y(-3)
' data-slug="move-down-on-arrow"><div class="patch"><table><tbody class="diff-unch"><tr><td class="linenum"><pre>33</pre></td><td class="linenum"><pre>33</pre></td><td><pre>        self.switch_costume("qbert1")</pre></td></tr><tr><td class="linenum"><pre>34</pre></td><td class="linenum"><pre>34</pre></td><td><pre>        self.go_to_front_layer()</pre></td></tr><tr><td class="linenum"><pre>35</pre></td><td class="linenum"><pre>35</pre></td><td><pre>        self.show()</pre></td></tr></tbody><tbody class="diff-add" data-added-text='
    @pytch.when_key_pressed("ArrowDown")
    def jump_down(self):
        self.switch_costume("qbert2")
        for frame in range(14):
            self.change_x(-2)
            self.change_y(-3)
'><tr><td class="linenum"></td><td class="linenum"><pre>36</pre></td><td><pre></pre></td></tr><tr><td class="linenum"></td><td class="linenum"><pre>37</pre></td><td><pre>    @pytch.when_key_pressed("ArrowDown")</pre></td></tr><tr><td class="linenum"></td><td class="linenum"><pre>38</pre></td><td><pre>    def jump_down(self):</pre></td></tr><tr><td class="linenum"></td><td class="linenum"><pre>39</pre></td><td><pre>        self.switch_costume("qbert2")</pre></td></tr><tr><td class="linenum"></td><td class="linenum"><pre>40</pre></td><td><pre>        for frame in range(14):</pre></td></tr><tr><td class="linenum"></td><td class="linenum"><pre>41</pre></td><td><pre>            self.change_x(-2)</pre></td></tr><tr><td class="linenum"></td><td class="linenum"><pre>42</pre></td><td><pre>            self.change_y(-3)</pre></td></tr></tbody></table></div></div><p>And moving Q*bert up is very similar:</p><div class="patch-container" data-code-as-of-commit='import pytch


class Background(pytch.Stage):
    Backdrops = ["background.png"]


class Block(pytch.Sprite):
    Costumes = ["block-unlit.png", "block-lit.png"]

    @pytch.when_green_flag_clicked
    def create_pyramid(self):
        for r in range(7):
            for b in range(7 - r):
                block_x = -150 + (b * 56) + (r * 28)
                block_y = -145 + (r * 42)
                self.go_to_xy(block_x, block_y)
                pytch.create_clone_of(self)
        self.hide()
        pytch.broadcast("set-up-qbert")


class Qbert(pytch.Sprite):
    Costumes = ["qbert0.png", "qbert1.png", "qbert2.png", "qbert3.png"]

    @pytch.when_green_flag_clicked
    def start_hidden(self):
        self.hide()

    @pytch.when_I_receive("set-up-qbert")
    def go_to_starting_position(self):
        self.go_to_xy(-150 + 3 * 56, -145 + (6 * 42) + 28)
        self.switch_costume("qbert1")
        self.go_to_front_layer()
        self.show()

    @pytch.when_key_pressed("ArrowUp")
    def jump_up(self):
        self.switch_costume("qbert0")
        for frame in range(14):
            self.change_x(2)
            self.change_y(3)

    @pytch.when_key_pressed("ArrowDown")
    def jump_down(self):
        self.switch_costume("qbert2")
        for frame in range(14):
            self.change_x(-2)
            self.change_y(-3)
' data-slug="move-up-on-arrow"><div class="patch"><table><tbody class="diff-unch"><tr><td class="linenum"><pre>34</pre></td><td class="linenum"><pre>34</pre></td><td><pre>        self.go_to_front_layer()</pre></td></tr><tr><td class="linenum"><pre>35</pre></td><td class="linenum"><pre>35</pre></td><td><pre>        self.show()</pre></td></tr><tr><td class="linenum"><pre>36</pre></td><td class="linenum"><pre>36</pre></td><td><pre></pre></td></tr></tbody><tbody class="diff-add" data-added-text='    @pytch.when_key_pressed("ArrowUp")
    def jump_up(self):
        self.switch_costume("qbert0")
        for frame in range(14):
            self.change_x(2)
            self.change_y(3)

'><tr><td class="linenum"></td><td class="linenum"><pre>37</pre></td><td><pre>    @pytch.when_key_pressed("ArrowUp")</pre></td></tr><tr><td class="linenum"></td><td class="linenum"><pre>38</pre></td><td><pre>    def jump_up(self):</pre></td></tr><tr><td class="linenum"></td><td class="linenum"><pre>39</pre></td><td><pre>        self.switch_costume("qbert0")</pre></td></tr><tr><td class="linenum"></td><td class="linenum"><pre>40</pre></td><td><pre>        for frame in range(14):</pre></td></tr><tr><td class="linenum"></td><td class="linenum"><pre>41</pre></td><td><pre>            self.change_x(2)</pre></td></tr><tr><td class="linenum"></td><td class="linenum"><pre>42</pre></td><td><pre>            self.change_y(3)</pre></td></tr><tr><td class="linenum"></td><td class="linenum"><pre>43</pre></td><td><pre></pre></td></tr></tbody><tbody class="diff-unch"><tr><td class="linenum"><pre>37</pre></td><td class="linenum"><pre>44</pre></td><td><pre>    @pytch.when_key_pressed("ArrowDown")</pre></td></tr><tr><td class="linenum"><pre>38</pre></td><td class="linenum"><pre>45</pre></td><td><pre>    def jump_down(self):</pre></td></tr><tr><td class="linenum"><pre>39</pre></td><td class="linenum"><pre>46</pre></td><td><pre>        self.switch_costume("qbert2")</pre></td></tr></tbody></table></div></div><p>If you try this now, it mostly works.  Q*bert can move up and down
(northeast and southwest on the screen), but there are two problems:</p><ul>
<li>Q*bert can go off the top or the bottom of the pyramid.</li>
<li>If you press the up-arrow key twice quickly, Q*bert moves at twice
  the speed.</li>
</ul><p>Because these problems affect moving up and moving down, it will make
sense to fix them just in once place in the code.  Our first step is
to <em>refactor</em> the code so the jumping logic only appears once.  That's
what we'll do next.</p></div><div class="chapter-content"><h2>Refactor the jumping code</h2><p>If you compare the <code>jump_down()</code> and <code>jump_up()</code> methods, you'll
notice they are very similar.  The differences are:</p><ul>
<li>the costume is different</li>
<li>the amount we change <em>x</em> by is different</li>
<li>the amount we change <em>y</em> by is different</li>
</ul><p>We'll create a <code>jump()</code> method which can work with different values
for these three things.  This is very much like a custom block in
Scratch.</p><div class="patch-container" data-code-as-of-commit='import pytch


class Background(pytch.Stage):
    Backdrops = ["background.png"]


class Block(pytch.Sprite):
    Costumes = ["block-unlit.png", "block-lit.png"]

    @pytch.when_green_flag_clicked
    def create_pyramid(self):
        for r in range(7):
            for b in range(7 - r):
                block_x = -150 + (b * 56) + (r * 28)
                block_y = -145 + (r * 42)
                self.go_to_xy(block_x, block_y)
                pytch.create_clone_of(self)
        self.hide()
        pytch.broadcast("set-up-qbert")


class Qbert(pytch.Sprite):
    Costumes = ["qbert0.png", "qbert1.png", "qbert2.png", "qbert3.png"]

    @pytch.when_green_flag_clicked
    def start_hidden(self):
        self.hide()

    @pytch.when_I_receive("set-up-qbert")
    def go_to_starting_position(self):
        self.go_to_xy(-150 + 3 * 56, -145 + (6 * 42) + 28)
        self.switch_costume("qbert1")
        self.go_to_front_layer()
        self.show()

    def jump(self, x_speed, y_speed, costume):
        self.switch_costume(costume)
        for frame in range(14):
            self.change_x(x_speed)
            self.change_y(y_speed)

    @pytch.when_key_pressed("ArrowUp")
    def jump_up(self):
        self.switch_costume("qbert0")
        for frame in range(14):
            self.change_x(2)
            self.change_y(3)

    @pytch.when_key_pressed("ArrowDown")
    def jump_down(self):
        self.switch_costume("qbert2")
        for frame in range(14):
            self.change_x(-2)
            self.change_y(-3)
' data-slug="define-jump-method"><div class="patch"><table><tbody class="diff-unch"><tr><td class="linenum"><pre>34</pre></td><td class="linenum"><pre>34</pre></td><td><pre>        self.go_to_front_layer()</pre></td></tr><tr><td class="linenum"><pre>35</pre></td><td class="linenum"><pre>35</pre></td><td><pre>        self.show()</pre></td></tr><tr><td class="linenum"><pre>36</pre></td><td class="linenum"><pre>36</pre></td><td><pre></pre></td></tr></tbody><tbody class="diff-add" data-added-text="    def jump(self, x_speed, y_speed, costume):
        self.switch_costume(costume)
        for frame in range(14):
            self.change_x(x_speed)
            self.change_y(y_speed)

"><tr><td class="linenum"></td><td class="linenum"><pre>37</pre></td><td><pre>    def jump(self, x_speed, y_speed, costume):</pre></td></tr><tr><td class="linenum"></td><td class="linenum"><pre>38</pre></td><td><pre>        self.switch_costume(costume)</pre></td></tr><tr><td class="linenum"></td><td class="linenum"><pre>39</pre></td><td><pre>        for frame in range(14):</pre></td></tr><tr><td class="linenum"></td><td class="linenum"><pre>40</pre></td><td><pre>            self.change_x(x_speed)</pre></td></tr><tr><td class="linenum"></td><td class="linenum"><pre>41</pre></td><td><pre>            self.change_y(y_speed)</pre></td></tr><tr><td class="linenum"></td><td class="linenum"><pre>42</pre></td><td><pre></pre></td></tr></tbody><tbody class="diff-unch"><tr><td class="linenum"><pre>37</pre></td><td class="linenum"><pre>43</pre></td><td><pre>    @pytch.when_key_pressed("ArrowUp")</pre></td></tr><tr><td class="linenum"><pre>38</pre></td><td class="linenum"><pre>44</pre></td><td><pre>    def jump_up(self):</pre></td></tr><tr><td class="linenum"><pre>39</pre></td><td class="linenum"><pre>45</pre></td><td><pre>        self.switch_costume("qbert0")</pre></td></tr></tbody></table></div></div><p>And now we can simplify the original <code>jump_up()</code> method, by calling
our new method with the right values for the <em>x</em>-speed, <em>y</em>-speed, and
costume name:</p><div class="patch-container" data-code-as-of-commit='import pytch


class Background(pytch.Stage):
    Backdrops = ["background.png"]


class Block(pytch.Sprite):
    Costumes = ["block-unlit.png", "block-lit.png"]

    @pytch.when_green_flag_clicked
    def create_pyramid(self):
        for r in range(7):
            for b in range(7 - r):
                block_x = -150 + (b * 56) + (r * 28)
                block_y = -145 + (r * 42)
                self.go_to_xy(block_x, block_y)
                pytch.create_clone_of(self)
        self.hide()
        pytch.broadcast("set-up-qbert")


class Qbert(pytch.Sprite):
    Costumes = ["qbert0.png", "qbert1.png", "qbert2.png", "qbert3.png"]

    @pytch.when_green_flag_clicked
    def start_hidden(self):
        self.hide()

    @pytch.when_I_receive("set-up-qbert")
    def go_to_starting_position(self):
        self.go_to_xy(-150 + 3 * 56, -145 + (6 * 42) + 28)
        self.switch_costume("qbert1")
        self.go_to_front_layer()
        self.show()

    def jump(self, x_speed, y_speed, costume):
        self.switch_costume(costume)
        for frame in range(14):
            self.change_x(x_speed)
            self.change_y(y_speed)

    @pytch.when_key_pressed("ArrowUp")
    def jump_up(self):
        self.jump(2, 3, "qbert0")

    @pytch.when_key_pressed("ArrowDown")
    def jump_down(self):
        self.switch_costume("qbert2")
        for frame in range(14):
            self.change_x(-2)
            self.change_y(-3)
' data-slug="simplify-jump-up-method"><div class="patch"><table><tbody class="diff-unch"><tr><td class="linenum"><pre>42</pre></td><td class="linenum"><pre>42</pre></td><td><pre></pre></td></tr><tr><td class="linenum"><pre>43</pre></td><td class="linenum"><pre>43</pre></td><td><pre>    @pytch.when_key_pressed("ArrowUp")</pre></td></tr><tr><td class="linenum"><pre>44</pre></td><td class="linenum"><pre>44</pre></td><td><pre>    def jump_up(self):</pre></td></tr></tbody><tbody class="diff-del"><tr><td class="linenum"><pre>45</pre></td><td class="linenum"></td><td><pre>        self.switch_costume("qbert0")</pre></td></tr><tr><td class="linenum"><pre>46</pre></td><td class="linenum"></td><td><pre>        for frame in range(14):</pre></td></tr><tr><td class="linenum"><pre>47</pre></td><td class="linenum"></td><td><pre>            self.change_x(2)</pre></td></tr><tr><td class="linenum"><pre>48</pre></td><td class="linenum"></td><td><pre>            self.change_y(3)</pre></td></tr></tbody><tbody class="diff-add" data-added-text='        self.jump(2, 3, "qbert0")
'><tr><td class="linenum"></td><td class="linenum"><pre>45</pre></td><td><pre>        self.jump(2, 3, "qbert0")</pre></td></tr></tbody><tbody class="diff-unch"><tr><td class="linenum"><pre>49</pre></td><td class="linenum"><pre>46</pre></td><td><pre></pre></td></tr><tr><td class="linenum"><pre>50</pre></td><td class="linenum"><pre>47</pre></td><td><pre>    @pytch.when_key_pressed("ArrowDown")</pre></td></tr><tr><td class="linenum"><pre>51</pre></td><td class="linenum"><pre>48</pre></td><td><pre>    def jump_down(self):</pre></td></tr></tbody></table></div></div><p>We can simplify the <code>jump_down()</code> method in the same way:</p><div class="patch-container" data-code-as-of-commit='import pytch


class Background(pytch.Stage):
    Backdrops = ["background.png"]


class Block(pytch.Sprite):
    Costumes = ["block-unlit.png", "block-lit.png"]

    @pytch.when_green_flag_clicked
    def create_pyramid(self):
        for r in range(7):
            for b in range(7 - r):
                block_x = -150 + (b * 56) + (r * 28)
                block_y = -145 + (r * 42)
                self.go_to_xy(block_x, block_y)
                pytch.create_clone_of(self)
        self.hide()
        pytch.broadcast("set-up-qbert")


class Qbert(pytch.Sprite):
    Costumes = ["qbert0.png", "qbert1.png", "qbert2.png", "qbert3.png"]

    @pytch.when_green_flag_clicked
    def start_hidden(self):
        self.hide()

    @pytch.when_I_receive("set-up-qbert")
    def go_to_starting_position(self):
        self.go_to_xy(-150 + 3 * 56, -145 + (6 * 42) + 28)
        self.switch_costume("qbert1")
        self.go_to_front_layer()
        self.show()

    def jump(self, x_speed, y_speed, costume):
        self.switch_costume(costume)
        for frame in range(14):
            self.change_x(x_speed)
            self.change_y(y_speed)

    @pytch.when_key_pressed("ArrowUp")
    def jump_up(self):
        self.jump(2, 3, "qbert0")

    @pytch.when_key_pressed("ArrowDown")
    def jump_down(self):
        self.jump(-2, -3, "qbert2")
' data-slug="simplify-jump-down-method"><div class="patch"><table><tbody class="diff-unch"><tr><td class="linenum"><pre>46</pre></td><td class="linenum"><pre>46</pre></td><td><pre></pre></td></tr><tr><td class="linenum"><pre>47</pre></td><td class="linenum"><pre>47</pre></td><td><pre>    @pytch.when_key_pressed("ArrowDown")</pre></td></tr><tr><td class="linenum"><pre>48</pre></td><td class="linenum"><pre>48</pre></td><td><pre>    def jump_down(self):</pre></td></tr></tbody><tbody class="diff-del"><tr><td class="linenum"><pre>49</pre></td><td class="linenum"></td><td><pre>        self.switch_costume("qbert2")</pre></td></tr><tr><td class="linenum"><pre>50</pre></td><td class="linenum"></td><td><pre>        for frame in range(14):</pre></td></tr><tr><td class="linenum"><pre>51</pre></td><td class="linenum"></td><td><pre>            self.change_x(-2)</pre></td></tr><tr><td class="linenum"><pre>52</pre></td><td class="linenum"></td><td><pre>            self.change_y(-3)</pre></td></tr></tbody><tbody class="diff-add" data-added-text='        self.jump(-2, -3, "qbert2")
'><tr><td class="linenum"></td><td class="linenum"><pre>49</pre></td><td><pre>        self.jump(-2, -3, "qbert2")</pre></td></tr></tbody></table></div></div></div><div class="chapter-content"><h2>Fix the 'double speed jump' problem</h2><p>Now there's only one place we'll need to look at to fix the first of
our problems, which was that quickly pressing an arrow key twice makes
Q*bert move at double speed.  We only need to look at the <code>jump()</code>
method.</p><p>The problem is that the player might press an arrow key while we're in
the middle of doing the jump.  We'll fix this by recording whether
we're in the middle of a jump, and ignoring arrow key presses if we
are.</p><p>The first step is to create an <em>instance variable</em>, which is very much
like a 'for this sprite only' variable in Scratch.  When we're setting
Q*bert up (in response to the <code>"set-up-qbert"</code> message), we'll set
this variable to say we are <em>not</em> currently jumping:</p><div class="patch-container" data-code-as-of-commit='import pytch


class Background(pytch.Stage):
    Backdrops = ["background.png"]


class Block(pytch.Sprite):
    Costumes = ["block-unlit.png", "block-lit.png"]

    @pytch.when_green_flag_clicked
    def create_pyramid(self):
        for r in range(7):
            for b in range(7 - r):
                block_x = -150 + (b * 56) + (r * 28)
                block_y = -145 + (r * 42)
                self.go_to_xy(block_x, block_y)
                pytch.create_clone_of(self)
        self.hide()
        pytch.broadcast("set-up-qbert")


class Qbert(pytch.Sprite):
    Costumes = ["qbert0.png", "qbert1.png", "qbert2.png", "qbert3.png"]

    @pytch.when_green_flag_clicked
    def start_hidden(self):
        self.hide()

    @pytch.when_I_receive("set-up-qbert")
    def go_to_starting_position(self):
        self.go_to_xy(-150 + 3 * 56, -145 + (6 * 42) + 28)
        self.switch_costume("qbert1")
        self.go_to_front_layer()
        self.show()
        self.jumping = False

    def jump(self, x_speed, y_speed, costume):
        self.switch_costume(costume)
        for frame in range(14):
            self.change_x(x_speed)
            self.change_y(y_speed)

    @pytch.when_key_pressed("ArrowUp")
    def jump_up(self):
        self.jump(2, 3, "qbert0")

    @pytch.when_key_pressed("ArrowDown")
    def jump_down(self):
        self.jump(-2, -3, "qbert2")
' data-slug="initialise-jumping-slot"><div class="patch"><table><tbody class="diff-unch"><tr><td class="linenum"><pre>33</pre></td><td class="linenum"><pre>33</pre></td><td><pre>        self.switch_costume("qbert1")</pre></td></tr><tr><td class="linenum"><pre>34</pre></td><td class="linenum"><pre>34</pre></td><td><pre>        self.go_to_front_layer()</pre></td></tr><tr><td class="linenum"><pre>35</pre></td><td class="linenum"><pre>35</pre></td><td><pre>        self.show()</pre></td></tr></tbody><tbody class="diff-add" data-added-text="        self.jumping = False
"><tr><td class="linenum"></td><td class="linenum"><pre>36</pre></td><td><pre>        self.jumping = False</pre></td></tr></tbody><tbody class="diff-unch"><tr><td class="linenum"><pre>36</pre></td><td class="linenum"><pre>37</pre></td><td><pre></pre></td></tr><tr><td class="linenum"><pre>37</pre></td><td class="linenum"><pre>38</pre></td><td><pre>    def jump(self, x_speed, y_speed, costume):</pre></td></tr><tr><td class="linenum"><pre>38</pre></td><td class="linenum"><pre>39</pre></td><td><pre>        self.switch_costume(costume)</pre></td></tr></tbody></table></div></div><p>Then the first thing we'll do when jumping is to record that we are
jumping, and then record that we're <em>not</em> jumping once we've finished
that jump:</p><div class="patch-container" data-code-as-of-commit='import pytch


class Background(pytch.Stage):
    Backdrops = ["background.png"]


class Block(pytch.Sprite):
    Costumes = ["block-unlit.png", "block-lit.png"]

    @pytch.when_green_flag_clicked
    def create_pyramid(self):
        for r in range(7):
            for b in range(7 - r):
                block_x = -150 + (b * 56) + (r * 28)
                block_y = -145 + (r * 42)
                self.go_to_xy(block_x, block_y)
                pytch.create_clone_of(self)
        self.hide()
        pytch.broadcast("set-up-qbert")


class Qbert(pytch.Sprite):
    Costumes = ["qbert0.png", "qbert1.png", "qbert2.png", "qbert3.png"]

    @pytch.when_green_flag_clicked
    def start_hidden(self):
        self.hide()

    @pytch.when_I_receive("set-up-qbert")
    def go_to_starting_position(self):
        self.go_to_xy(-150 + 3 * 56, -145 + (6 * 42) + 28)
        self.switch_costume("qbert1")
        self.go_to_front_layer()
        self.show()
        self.jumping = False

    def jump(self, x_speed, y_speed, costume):
        self.jumping = True
        self.switch_costume(costume)
        for frame in range(14):
            self.change_x(x_speed)
            self.change_y(y_speed)
        self.jumping = False

    @pytch.when_key_pressed("ArrowUp")
    def jump_up(self):
        self.jump(2, 3, "qbert0")

    @pytch.when_key_pressed("ArrowDown")
    def jump_down(self):
        self.jump(-2, -3, "qbert2")
' data-slug="note-when-jumping"><div class="patch"><table><tbody class="diff-unch"><tr><td class="linenum"><pre>36</pre></td><td class="linenum"><pre>36</pre></td><td><pre>        self.jumping = False</pre></td></tr><tr><td class="linenum"><pre>37</pre></td><td class="linenum"><pre>37</pre></td><td><pre></pre></td></tr><tr><td class="linenum"><pre>38</pre></td><td class="linenum"><pre>38</pre></td><td><pre>    def jump(self, x_speed, y_speed, costume):</pre></td></tr></tbody><tbody class="diff-add" data-added-text="        self.jumping = True
"><tr><td class="linenum"></td><td class="linenum"><pre>39</pre></td><td><pre>        self.jumping = True</pre></td></tr></tbody><tbody class="diff-unch"><tr><td class="linenum"><pre>39</pre></td><td class="linenum"><pre>40</pre></td><td><pre>        self.switch_costume(costume)</pre></td></tr><tr><td class="linenum"><pre>40</pre></td><td class="linenum"><pre>41</pre></td><td><pre>        for frame in range(14):</pre></td></tr><tr><td class="linenum"><pre>41</pre></td><td class="linenum"><pre>42</pre></td><td><pre>            self.change_x(x_speed)</pre></td></tr><tr><td class="linenum"><pre>42</pre></td><td class="linenum"><pre>43</pre></td><td><pre>            self.change_y(y_speed)</pre></td></tr></tbody><tbody class="diff-add" data-added-text="        self.jumping = False
"><tr><td class="linenum"></td><td class="linenum"><pre>44</pre></td><td><pre>        self.jumping = False</pre></td></tr></tbody><tbody class="diff-unch"><tr><td class="linenum"><pre>43</pre></td><td class="linenum"><pre>45</pre></td><td><pre></pre></td></tr><tr><td class="linenum"><pre>44</pre></td><td class="linenum"><pre>46</pre></td><td><pre>    @pytch.when_key_pressed("ArrowUp")</pre></td></tr><tr><td class="linenum"><pre>45</pre></td><td class="linenum"><pre>47</pre></td><td><pre>    def jump_up(self):</pre></td></tr></tbody></table></div></div><p>Now we can just leave the <code>jump()</code> method early, without doing
anything, if we're already mid-jump:</p><div class="patch-container" data-code-as-of-commit='import pytch


class Background(pytch.Stage):
    Backdrops = ["background.png"]


class Block(pytch.Sprite):
    Costumes = ["block-unlit.png", "block-lit.png"]

    @pytch.when_green_flag_clicked
    def create_pyramid(self):
        for r in range(7):
            for b in range(7 - r):
                block_x = -150 + (b * 56) + (r * 28)
                block_y = -145 + (r * 42)
                self.go_to_xy(block_x, block_y)
                pytch.create_clone_of(self)
        self.hide()
        pytch.broadcast("set-up-qbert")


class Qbert(pytch.Sprite):
    Costumes = ["qbert0.png", "qbert1.png", "qbert2.png", "qbert3.png"]

    @pytch.when_green_flag_clicked
    def start_hidden(self):
        self.hide()

    @pytch.when_I_receive("set-up-qbert")
    def go_to_starting_position(self):
        self.go_to_xy(-150 + 3 * 56, -145 + (6 * 42) + 28)
        self.switch_costume("qbert1")
        self.go_to_front_layer()
        self.show()
        self.jumping = False

    def jump(self, x_speed, y_speed, costume):
        if self.jumping:
            return
        self.jumping = True
        self.switch_costume(costume)
        for frame in range(14):
            self.change_x(x_speed)
            self.change_y(y_speed)
        self.jumping = False

    @pytch.when_key_pressed("ArrowUp")
    def jump_up(self):
        self.jump(2, 3, "qbert0")

    @pytch.when_key_pressed("ArrowDown")
    def jump_down(self):
        self.jump(-2, -3, "qbert2")
' data-slug="do-not-jump-if-already-jumping"><div class="patch"><table><tbody class="diff-unch"><tr><td class="linenum"><pre>36</pre></td><td class="linenum"><pre>36</pre></td><td><pre>        self.jumping = False</pre></td></tr><tr><td class="linenum"><pre>37</pre></td><td class="linenum"><pre>37</pre></td><td><pre></pre></td></tr><tr><td class="linenum"><pre>38</pre></td><td class="linenum"><pre>38</pre></td><td><pre>    def jump(self, x_speed, y_speed, costume):</pre></td></tr></tbody><tbody class="diff-add" data-added-text="        if self.jumping:
            return
"><tr><td class="linenum"></td><td class="linenum"><pre>39</pre></td><td><pre>        if self.jumping:</pre></td></tr><tr><td class="linenum"></td><td class="linenum"><pre>40</pre></td><td><pre>            return</pre></td></tr></tbody><tbody class="diff-unch"><tr><td class="linenum"><pre>39</pre></td><td class="linenum"><pre>41</pre></td><td><pre>        self.jumping = True</pre></td></tr><tr><td class="linenum"><pre>40</pre></td><td class="linenum"><pre>42</pre></td><td><pre>        self.switch_costume(costume)</pre></td></tr><tr><td class="linenum"><pre>41</pre></td><td class="linenum"><pre>43</pre></td><td><pre>        for frame in range(14):</pre></td></tr></tbody></table></div></div><p>(There's still the problem of being able to go off the top or bottom
of the pyramid.  We'll get to that later.)</p></div><div class="chapter-content"><h2>Finish the movement controls: left and right</h2><p>With this done, it's now quite easy to let the player move in the
other two directions.</p><p>We handle the <code>ArrowLeft</code> keypress to let the player move Q*bert
left, which is northwest on the screen:</p><div class="patch-container" data-code-as-of-commit='import pytch


class Background(pytch.Stage):
    Backdrops = ["background.png"]


class Block(pytch.Sprite):
    Costumes = ["block-unlit.png", "block-lit.png"]

    @pytch.when_green_flag_clicked
    def create_pyramid(self):
        for r in range(7):
            for b in range(7 - r):
                block_x = -150 + (b * 56) + (r * 28)
                block_y = -145 + (r * 42)
                self.go_to_xy(block_x, block_y)
                pytch.create_clone_of(self)
        self.hide()
        pytch.broadcast("set-up-qbert")


class Qbert(pytch.Sprite):
    Costumes = ["qbert0.png", "qbert1.png", "qbert2.png", "qbert3.png"]

    @pytch.when_green_flag_clicked
    def start_hidden(self):
        self.hide()

    @pytch.when_I_receive("set-up-qbert")
    def go_to_starting_position(self):
        self.go_to_xy(-150 + 3 * 56, -145 + (6 * 42) + 28)
        self.switch_costume("qbert1")
        self.go_to_front_layer()
        self.show()
        self.jumping = False

    def jump(self, x_speed, y_speed, costume):
        if self.jumping:
            return
        self.jumping = True
        self.switch_costume(costume)
        for frame in range(14):
            self.change_x(x_speed)
            self.change_y(y_speed)
        self.jumping = False

    @pytch.when_key_pressed("ArrowUp")
    def jump_up(self):
        self.jump(2, 3, "qbert0")

    @pytch.when_key_pressed("ArrowDown")
    def jump_down(self):
        self.jump(-2, -3, "qbert2")

    @pytch.when_key_pressed("ArrowLeft")
    def jump_left(self):
        self.jump(-2, 3, "qbert3")
' data-slug="move-left-on-arrow"><div class="patch"><table><tbody class="diff-unch"><tr><td class="linenum"><pre>52</pre></td><td class="linenum"><pre>52</pre></td><td><pre>    @pytch.when_key_pressed("ArrowDown")</pre></td></tr><tr><td class="linenum"><pre>53</pre></td><td class="linenum"><pre>53</pre></td><td><pre>    def jump_down(self):</pre></td></tr><tr><td class="linenum"><pre>54</pre></td><td class="linenum"><pre>54</pre></td><td><pre>        self.jump(-2, -3, "qbert2")</pre></td></tr></tbody><tbody class="diff-add" data-added-text='
    @pytch.when_key_pressed("ArrowLeft")
    def jump_left(self):
        self.jump(-2, 3, "qbert3")
'><tr><td class="linenum"></td><td class="linenum"><pre>55</pre></td><td><pre></pre></td></tr><tr><td class="linenum"></td><td class="linenum"><pre>56</pre></td><td><pre>    @pytch.when_key_pressed("ArrowLeft")</pre></td></tr><tr><td class="linenum"></td><td class="linenum"><pre>57</pre></td><td><pre>    def jump_left(self):</pre></td></tr><tr><td class="linenum"></td><td class="linenum"><pre>58</pre></td><td><pre>        self.jump(-2, 3, "qbert3")</pre></td></tr></tbody></table></div></div><p>and the <code>ArrowRight</code> keypress to let the player move Q*bert right,
which is southeast on the screen:</p><div class="patch-container" data-code-as-of-commit='import pytch


class Background(pytch.Stage):
    Backdrops = ["background.png"]


class Block(pytch.Sprite):
    Costumes = ["block-unlit.png", "block-lit.png"]

    @pytch.when_green_flag_clicked
    def create_pyramid(self):
        for r in range(7):
            for b in range(7 - r):
                block_x = -150 + (b * 56) + (r * 28)
                block_y = -145 + (r * 42)
                self.go_to_xy(block_x, block_y)
                pytch.create_clone_of(self)
        self.hide()
        pytch.broadcast("set-up-qbert")


class Qbert(pytch.Sprite):
    Costumes = ["qbert0.png", "qbert1.png", "qbert2.png", "qbert3.png"]

    @pytch.when_green_flag_clicked
    def start_hidden(self):
        self.hide()

    @pytch.when_I_receive("set-up-qbert")
    def go_to_starting_position(self):
        self.go_to_xy(-150 + 3 * 56, -145 + (6 * 42) + 28)
        self.switch_costume("qbert1")
        self.go_to_front_layer()
        self.show()
        self.jumping = False

    def jump(self, x_speed, y_speed, costume):
        if self.jumping:
            return
        self.jumping = True
        self.switch_costume(costume)
        for frame in range(14):
            self.change_x(x_speed)
            self.change_y(y_speed)
        self.jumping = False

    @pytch.when_key_pressed("ArrowUp")
    def jump_up(self):
        self.jump(2, 3, "qbert0")

    @pytch.when_key_pressed("ArrowDown")
    def jump_down(self):
        self.jump(-2, -3, "qbert2")

    @pytch.when_key_pressed("ArrowLeft")
    def jump_left(self):
        self.jump(-2, 3, "qbert3")

    @pytch.when_key_pressed("ArrowRight")
    def jump_right(self):
        self.jump(2, -3, "qbert1")
' data-slug="move-right-on-arrow"><div class="patch"><table><tbody class="diff-unch"><tr><td class="linenum"><pre>56</pre></td><td class="linenum"><pre>56</pre></td><td><pre>    @pytch.when_key_pressed("ArrowLeft")</pre></td></tr><tr><td class="linenum"><pre>57</pre></td><td class="linenum"><pre>57</pre></td><td><pre>    def jump_left(self):</pre></td></tr><tr><td class="linenum"><pre>58</pre></td><td class="linenum"><pre>58</pre></td><td><pre>        self.jump(-2, 3, "qbert3")</pre></td></tr></tbody><tbody class="diff-add" data-added-text='
    @pytch.when_key_pressed("ArrowRight")
    def jump_right(self):
        self.jump(2, -3, "qbert1")
'><tr><td class="linenum"></td><td class="linenum"><pre>59</pre></td><td><pre></pre></td></tr><tr><td class="linenum"></td><td class="linenum"><pre>60</pre></td><td><pre>    @pytch.when_key_pressed("ArrowRight")</pre></td></tr><tr><td class="linenum"></td><td class="linenum"><pre>61</pre></td><td><pre>    def jump_right(self):</pre></td></tr><tr><td class="linenum"></td><td class="linenum"><pre>62</pre></td><td><pre>        self.jump(2, -3, "qbert1")</pre></td></tr></tbody></table></div></div></div><div class="chapter-content"><h2>Add a little bounce to the jump</h2><p>To make the game look better, we'll add a bounce to Q*bert's
movement.  We want a bit of extra upwards speed in the <em>y</em> direction
at the start of a jump, and a bit of extra downwards speed at the end
of a jump.  Each jump is 14 frames long, so we'll define a <em>list</em> of
the extra <em>y</em> speeds:</p><div class="patch-container" data-code-as-of-commit='import pytch


class Background(pytch.Stage):
    Backdrops = ["background.png"]


class Block(pytch.Sprite):
    Costumes = ["block-unlit.png", "block-lit.png"]

    @pytch.when_green_flag_clicked
    def create_pyramid(self):
        for r in range(7):
            for b in range(7 - r):
                block_x = -150 + (b * 56) + (r * 28)
                block_y = -145 + (r * 42)
                self.go_to_xy(block_x, block_y)
                pytch.create_clone_of(self)
        self.hide()
        pytch.broadcast("set-up-qbert")


class Qbert(pytch.Sprite):
    Costumes = ["qbert0.png", "qbert1.png", "qbert2.png", "qbert3.png"]

    @pytch.when_green_flag_clicked
    def start_hidden(self):
        self.hide()

    # This list must have exactly 14 entries.
    bounce = [6, 4, 2, 1, 0, 0, 0, 0, 0, 0, -1, -2, -4, -6]

    @pytch.when_I_receive("set-up-qbert")
    def go_to_starting_position(self):
        self.go_to_xy(-150 + 3 * 56, -145 + (6 * 42) + 28)
        self.switch_costume("qbert1")
        self.go_to_front_layer()
        self.show()
        self.jumping = False

    def jump(self, x_speed, y_speed, costume):
        if self.jumping:
            return
        self.jumping = True
        self.switch_costume(costume)
        for frame in range(14):
            self.change_x(x_speed)
            self.change_y(y_speed)
        self.jumping = False

    @pytch.when_key_pressed("ArrowUp")
    def jump_up(self):
        self.jump(2, 3, "qbert0")

    @pytch.when_key_pressed("ArrowDown")
    def jump_down(self):
        self.jump(-2, -3, "qbert2")

    @pytch.when_key_pressed("ArrowLeft")
    def jump_left(self):
        self.jump(-2, 3, "qbert3")

    @pytch.when_key_pressed("ArrowRight")
    def jump_right(self):
        self.jump(2, -3, "qbert1")
' data-slug="define-bounce-list-of-y-speeds"><div class="patch"><table><tbody class="diff-unch"><tr><td class="linenum"><pre>27</pre></td><td class="linenum"><pre>27</pre></td><td><pre>    def start_hidden(self):</pre></td></tr><tr><td class="linenum"><pre>28</pre></td><td class="linenum"><pre>28</pre></td><td><pre>        self.hide()</pre></td></tr><tr><td class="linenum"><pre>29</pre></td><td class="linenum"><pre>29</pre></td><td><pre></pre></td></tr></tbody><tbody class="diff-add" data-added-text="    # This list must have exactly 14 entries.
    bounce = [6, 4, 2, 1, 0, 0, 0, 0, 0, 0, -1, -2, -4, -6]

"><tr><td class="linenum"></td><td class="linenum"><pre>30</pre></td><td><pre>    # This list must have exactly 14 entries.</pre></td></tr><tr><td class="linenum"></td><td class="linenum"><pre>31</pre></td><td><pre>    bounce = [6, 4, 2, 1, 0, 0, 0, 0, 0, 0, -1, -2, -4, -6]</pre></td></tr><tr><td class="linenum"></td><td class="linenum"><pre>32</pre></td><td><pre></pre></td></tr></tbody><tbody class="diff-unch"><tr><td class="linenum"><pre>30</pre></td><td class="linenum"><pre>33</pre></td><td><pre>    @pytch.when_I_receive("set-up-qbert")</pre></td></tr><tr><td class="linenum"><pre>31</pre></td><td class="linenum"><pre>34</pre></td><td><pre>    def go_to_starting_position(self):</pre></td></tr><tr><td class="linenum"><pre>32</pre></td><td class="linenum"><pre>35</pre></td><td><pre>        self.go_to_xy(-150 + 3 * 56, -145 + (6 * 42) + 28)</pre></td></tr></tbody></table></div></div><p>Those extra bits of speed all add up to zero, so Q*bert will still
end up in the right place at the end of their jump.</p><p>Again, we'll now see that it was worth our time to not have the
jumping code copied out four times, because we only need to change the
<code>jump()</code> method.  We include the right bounce amount when changing
<em>y</em>, depending on what frame we're on.  In Python, to get a particular
entry out of a list, we use square brackets <code>[]</code>, and we also have to
know that Python starts counting at <em>zero</em>.  This fits nicely with the
values <code>0</code>, <code>1</code>, ..., <code>13</code> that <code>range(14)</code> gives us.</p><div class="patch-container" data-code-as-of-commit='import pytch


class Background(pytch.Stage):
    Backdrops = ["background.png"]


class Block(pytch.Sprite):
    Costumes = ["block-unlit.png", "block-lit.png"]

    @pytch.when_green_flag_clicked
    def create_pyramid(self):
        for r in range(7):
            for b in range(7 - r):
                block_x = -150 + (b * 56) + (r * 28)
                block_y = -145 + (r * 42)
                self.go_to_xy(block_x, block_y)
                pytch.create_clone_of(self)
        self.hide()
        pytch.broadcast("set-up-qbert")


class Qbert(pytch.Sprite):
    Costumes = ["qbert0.png", "qbert1.png", "qbert2.png", "qbert3.png"]

    @pytch.when_green_flag_clicked
    def start_hidden(self):
        self.hide()

    # This list must have exactly 14 entries.
    bounce = [6, 4, 2, 1, 0, 0, 0, 0, 0, 0, -1, -2, -4, -6]

    @pytch.when_I_receive("set-up-qbert")
    def go_to_starting_position(self):
        self.go_to_xy(-150 + 3 * 56, -145 + (6 * 42) + 28)
        self.switch_costume("qbert1")
        self.go_to_front_layer()
        self.show()
        self.jumping = False

    def jump(self, x_speed, y_speed, costume):
        if self.jumping:
            return
        self.jumping = True
        self.switch_costume(costume)
        for frame in range(14):
            self.change_x(x_speed)
            self.change_y(y_speed + self.bounce[frame])
        self.jumping = False

    @pytch.when_key_pressed("ArrowUp")
    def jump_up(self):
        self.jump(2, 3, "qbert0")

    @pytch.when_key_pressed("ArrowDown")
    def jump_down(self):
        self.jump(-2, -3, "qbert2")

    @pytch.when_key_pressed("ArrowLeft")
    def jump_left(self):
        self.jump(-2, 3, "qbert3")

    @pytch.when_key_pressed("ArrowRight")
    def jump_right(self):
        self.jump(2, -3, "qbert1")
' data-slug="bounce-when-moving"><div class="patch"><table><tbody class="diff-unch"><tr><td class="linenum"><pre>45</pre></td><td class="linenum"><pre>45</pre></td><td><pre>        self.switch_costume(costume)</pre></td></tr><tr><td class="linenum"><pre>46</pre></td><td class="linenum"><pre>46</pre></td><td><pre>        for frame in range(14):</pre></td></tr><tr><td class="linenum"><pre>47</pre></td><td class="linenum"><pre>47</pre></td><td><pre>            self.change_x(x_speed)</pre></td></tr></tbody><tbody class="diff-del"><tr><td class="linenum"><pre>48</pre></td><td class="linenum"></td><td><pre>            self.change_y(y_speed)</pre></td></tr></tbody><tbody class="diff-add" data-added-text="            self.change_y(y_speed + self.bounce[frame])
"><tr><td class="linenum"></td><td class="linenum"><pre>48</pre></td><td><pre>            self.change_y(y_speed + self.bounce[frame])</pre></td></tr></tbody><tbody class="diff-unch"><tr><td class="linenum"><pre>49</pre></td><td class="linenum"><pre>49</pre></td><td><pre>        self.jumping = False</pre></td></tr><tr><td class="linenum"><pre>50</pre></td><td class="linenum"><pre>50</pre></td><td><pre></pre></td></tr><tr><td class="linenum"><pre>51</pre></td><td class="linenum"><pre>51</pre></td><td><pre>    @pytch.when_key_pressed("ArrowUp")</pre></td></tr></tbody></table></div></div><p>With this, the movement looks a lot better.</p></div><div class="chapter-content"><h2>Work out where on the pyramid we are</h2><p>We'll now work on the second problem we noticed, which was that
Q*bert can jump right off the top, bottom, or sides of the pyramid.
We'll make a method which works out which row we're on, and which
block within that row.  There's more maths here, to 'undo' the
calculation we did to find where to place each Block clone.</p><p><strong>TODO: Do we need to explain that?</strong></p><div class="patch-container" data-code-as-of-commit='import pytch


class Background(pytch.Stage):
    Backdrops = ["background.png"]


class Block(pytch.Sprite):
    Costumes = ["block-unlit.png", "block-lit.png"]

    @pytch.when_green_flag_clicked
    def create_pyramid(self):
        for r in range(7):
            for b in range(7 - r):
                block_x = -150 + (b * 56) + (r * 28)
                block_y = -145 + (r * 42)
                self.go_to_xy(block_x, block_y)
                pytch.create_clone_of(self)
        self.hide()
        pytch.broadcast("set-up-qbert")


class Qbert(pytch.Sprite):
    Costumes = ["qbert0.png", "qbert1.png", "qbert2.png", "qbert3.png"]

    @pytch.when_green_flag_clicked
    def start_hidden(self):
        self.hide()

    # This list must have exactly 14 entries.
    bounce = [6, 4, 2, 1, 0, 0, 0, 0, 0, 0, -1, -2, -4, -6]

    @pytch.when_I_receive("set-up-qbert")
    def go_to_starting_position(self):
        self.go_to_xy(-150 + 3 * 56, -145 + (6 * 42) + 28)
        self.switch_costume("qbert1")
        self.go_to_front_layer()
        self.show()
        self.jumping = False

    def pyramid_coordinates(self):
        y_on_stage = self.y_position
        pyramid_r = (y_on_stage + 145 - 28) / 42
        x_on_stage = self.x_position
        pyramid_b = (x_on_stage + 150 - pyramid_r * 28) / 56
        return (pyramid_r, pyramid_b)

    def jump(self, x_speed, y_speed, costume):
        if self.jumping:
            return
        self.jumping = True
        self.switch_costume(costume)
        for frame in range(14):
            self.change_x(x_speed)
            self.change_y(y_speed + self.bounce[frame])
        self.jumping = False

    @pytch.when_key_pressed("ArrowUp")
    def jump_up(self):
        self.jump(2, 3, "qbert0")

    @pytch.when_key_pressed("ArrowDown")
    def jump_down(self):
        self.jump(-2, -3, "qbert2")

    @pytch.when_key_pressed("ArrowLeft")
    def jump_left(self):
        self.jump(-2, 3, "qbert3")

    @pytch.when_key_pressed("ArrowRight")
    def jump_right(self):
        self.jump(2, -3, "qbert1")
' data-slug="method-to-compute-pyramid-coords"><div class="patch"><table><tbody class="diff-unch"><tr><td class="linenum"><pre>38</pre></td><td class="linenum"><pre>38</pre></td><td><pre>        self.show()</pre></td></tr><tr><td class="linenum"><pre>39</pre></td><td class="linenum"><pre>39</pre></td><td><pre>        self.jumping = False</pre></td></tr><tr><td class="linenum"><pre>40</pre></td><td class="linenum"><pre>40</pre></td><td><pre></pre></td></tr></tbody><tbody class="diff-add" data-added-text="    def pyramid_coordinates(self):
        y_on_stage = self.y_position
        pyramid_r = (y_on_stage + 145 - 28) / 42
        x_on_stage = self.x_position
        pyramid_b = (x_on_stage + 150 - pyramid_r * 28) / 56
        return (pyramid_r, pyramid_b)

"><tr><td class="linenum"></td><td class="linenum"><pre>41</pre></td><td><pre>    def pyramid_coordinates(self):</pre></td></tr><tr><td class="linenum"></td><td class="linenum"><pre>42</pre></td><td><pre>        y_on_stage = self.y_position</pre></td></tr><tr><td class="linenum"></td><td class="linenum"><pre>43</pre></td><td><pre>        pyramid_r = (y_on_stage + 145 - 28) / 42</pre></td></tr><tr><td class="linenum"></td><td class="linenum"><pre>44</pre></td><td><pre>        x_on_stage = self.x_position</pre></td></tr><tr><td class="linenum"></td><td class="linenum"><pre>45</pre></td><td><pre>        pyramid_b = (x_on_stage + 150 - pyramid_r * 28) / 56</pre></td></tr><tr><td class="linenum"></td><td class="linenum"><pre>46</pre></td><td><pre>        return (pyramid_r, pyramid_b)</pre></td></tr><tr><td class="linenum"></td><td class="linenum"><pre>47</pre></td><td><pre></pre></td></tr></tbody><tbody class="diff-unch"><tr><td class="linenum"><pre>41</pre></td><td class="linenum"><pre>48</pre></td><td><pre>    def jump(self, x_speed, y_speed, costume):</pre></td></tr><tr><td class="linenum"><pre>42</pre></td><td class="linenum"><pre>49</pre></td><td><pre>        if self.jumping:</pre></td></tr><tr><td class="linenum"><pre>43</pre></td><td class="linenum"><pre>50</pre></td><td><pre>            return</pre></td></tr></tbody></table></div></div><p>This method <em>returns a value</em>, like blocks such as <em>(mouse x)</em> in
Scratch.  The value here is a pair of numbers.  The first one is the
row, and the second the block within that row.</p><p>Nothing is using this method yet, though, so it's hard to tell if it's
working correctly.  We'll make it so pressing <code>"w"</code> (for 'where') will
print out where on the pyramid this code thinks we are:</p><div class="patch-container" data-code-as-of-commit='import pytch


class Background(pytch.Stage):
    Backdrops = ["background.png"]


class Block(pytch.Sprite):
    Costumes = ["block-unlit.png", "block-lit.png"]

    @pytch.when_green_flag_clicked
    def create_pyramid(self):
        for r in range(7):
            for b in range(7 - r):
                block_x = -150 + (b * 56) + (r * 28)
                block_y = -145 + (r * 42)
                self.go_to_xy(block_x, block_y)
                pytch.create_clone_of(self)
        self.hide()
        pytch.broadcast("set-up-qbert")


class Qbert(pytch.Sprite):
    Costumes = ["qbert0.png", "qbert1.png", "qbert2.png", "qbert3.png"]

    @pytch.when_green_flag_clicked
    def start_hidden(self):
        self.hide()

    # This list must have exactly 14 entries.
    bounce = [6, 4, 2, 1, 0, 0, 0, 0, 0, 0, -1, -2, -4, -6]

    @pytch.when_I_receive("set-up-qbert")
    def go_to_starting_position(self):
        self.go_to_xy(-150 + 3 * 56, -145 + (6 * 42) + 28)
        self.switch_costume("qbert1")
        self.go_to_front_layer()
        self.show()
        self.jumping = False

    def pyramid_coordinates(self):
        y_on_stage = self.y_position
        pyramid_r = (y_on_stage + 145 - 28) / 42
        x_on_stage = self.x_position
        pyramid_b = (x_on_stage + 150 - pyramid_r * 28) / 56
        return (pyramid_r, pyramid_b)

    @pytch.when_key_pressed("w")
    def print_coordinates(self):
        print("Qbert is on row %d block %d" % self.pyramid_coordinates())

    def jump(self, x_speed, y_speed, costume):
        if self.jumping:
            return
        self.jumping = True
        self.switch_costume(costume)
        for frame in range(14):
            self.change_x(x_speed)
            self.change_y(y_speed + self.bounce[frame])
        self.jumping = False

    @pytch.when_key_pressed("ArrowUp")
    def jump_up(self):
        self.jump(2, 3, "qbert0")

    @pytch.when_key_pressed("ArrowDown")
    def jump_down(self):
        self.jump(-2, -3, "qbert2")

    @pytch.when_key_pressed("ArrowLeft")
    def jump_left(self):
        self.jump(-2, 3, "qbert3")

    @pytch.when_key_pressed("ArrowRight")
    def jump_right(self):
        self.jump(2, -3, "qbert1")
' data-slug="add-diagnostics-for-coordinates"><div class="patch"><table><tbody class="diff-unch"><tr><td class="linenum"><pre>45</pre></td><td class="linenum"><pre>45</pre></td><td><pre>        pyramid_b = (x_on_stage + 150 - pyramid_r * 28) / 56</pre></td></tr><tr><td class="linenum"><pre>46</pre></td><td class="linenum"><pre>46</pre></td><td><pre>        return (pyramid_r, pyramid_b)</pre></td></tr><tr><td class="linenum"><pre>47</pre></td><td class="linenum"><pre>47</pre></td><td><pre></pre></td></tr></tbody><tbody class="diff-add" data-added-text='    @pytch.when_key_pressed("w")
    def print_coordinates(self):
        print("Qbert is on row %d block %d" % self.pyramid_coordinates())

'><tr><td class="linenum"></td><td class="linenum"><pre>48</pre></td><td><pre>    @pytch.when_key_pressed("w")</pre></td></tr><tr><td class="linenum"></td><td class="linenum"><pre>49</pre></td><td><pre>    def print_coordinates(self):</pre></td></tr><tr><td class="linenum"></td><td class="linenum"><pre>50</pre></td><td><pre>        print("Qbert is on row %d block %d" % self.pyramid_coordinates())</pre></td></tr><tr><td class="linenum"></td><td class="linenum"><pre>51</pre></td><td><pre></pre></td></tr></tbody><tbody class="diff-unch"><tr><td class="linenum"><pre>48</pre></td><td class="linenum"><pre>52</pre></td><td><pre>    def jump(self, x_speed, y_speed, costume):</pre></td></tr><tr><td class="linenum"><pre>49</pre></td><td class="linenum"><pre>53</pre></td><td><pre>        if self.jumping:</pre></td></tr><tr><td class="linenum"><pre>50</pre></td><td class="linenum"><pre>54</pre></td><td><pre>            return</pre></td></tr></tbody></table></div></div><p>Try this:</p><ul>
<li>Switch to the <em>Output</em> tab.</li>
<li>Green-flag the project.</li>
<li>Move Q*bert around, and press the <code>"w"</code> key to check the code is
  working out Q*bert's position correctly.</li>
</ul><p>Remember, row zero is the bottom row, and block zero is the far-left
block on each row.</p><p>You can come back to the tutorial by clicking on the <em>Tutorial</em> tab
header.  Once you're happy that the calculations are correct, you can
remove the temporary code:</p><div class="patch-container" data-code-as-of-commit='import pytch


class Background(pytch.Stage):
    Backdrops = ["background.png"]


class Block(pytch.Sprite):
    Costumes = ["block-unlit.png", "block-lit.png"]

    @pytch.when_green_flag_clicked
    def create_pyramid(self):
        for r in range(7):
            for b in range(7 - r):
                block_x = -150 + (b * 56) + (r * 28)
                block_y = -145 + (r * 42)
                self.go_to_xy(block_x, block_y)
                pytch.create_clone_of(self)
        self.hide()
        pytch.broadcast("set-up-qbert")


class Qbert(pytch.Sprite):
    Costumes = ["qbert0.png", "qbert1.png", "qbert2.png", "qbert3.png"]

    @pytch.when_green_flag_clicked
    def start_hidden(self):
        self.hide()

    # This list must have exactly 14 entries.
    bounce = [6, 4, 2, 1, 0, 0, 0, 0, 0, 0, -1, -2, -4, -6]

    @pytch.when_I_receive("set-up-qbert")
    def go_to_starting_position(self):
        self.go_to_xy(-150 + 3 * 56, -145 + (6 * 42) + 28)
        self.switch_costume("qbert1")
        self.go_to_front_layer()
        self.show()
        self.jumping = False

    def pyramid_coordinates(self):
        y_on_stage = self.y_position
        pyramid_r = (y_on_stage + 145 - 28) / 42
        x_on_stage = self.x_position
        pyramid_b = (x_on_stage + 150 - pyramid_r * 28) / 56
        return (pyramid_r, pyramid_b)

    def jump(self, x_speed, y_speed, costume):
        if self.jumping:
            return
        self.jumping = True
        self.switch_costume(costume)
        for frame in range(14):
            self.change_x(x_speed)
            self.change_y(y_speed + self.bounce[frame])
        self.jumping = False

    @pytch.when_key_pressed("ArrowUp")
    def jump_up(self):
        self.jump(2, 3, "qbert0")

    @pytch.when_key_pressed("ArrowDown")
    def jump_down(self):
        self.jump(-2, -3, "qbert2")

    @pytch.when_key_pressed("ArrowLeft")
    def jump_left(self):
        self.jump(-2, 3, "qbert3")

    @pytch.when_key_pressed("ArrowRight")
    def jump_right(self):
        self.jump(2, -3, "qbert1")
' data-slug="remove-pyramid-coords-diagnostics"><div class="patch"><table><tbody class="diff-unch"><tr><td class="linenum"><pre>45</pre></td><td class="linenum"><pre>45</pre></td><td><pre>        pyramid_b = (x_on_stage + 150 - pyramid_r * 28) / 56</pre></td></tr><tr><td class="linenum"><pre>46</pre></td><td class="linenum"><pre>46</pre></td><td><pre>        return (pyramid_r, pyramid_b)</pre></td></tr><tr><td class="linenum"><pre>47</pre></td><td class="linenum"><pre>47</pre></td><td><pre></pre></td></tr></tbody><tbody class="diff-del"><tr><td class="linenum"><pre>48</pre></td><td class="linenum"></td><td><pre>    @pytch.when_key_pressed("w")</pre></td></tr><tr><td class="linenum"><pre>49</pre></td><td class="linenum"></td><td><pre>    def print_coordinates(self):</pre></td></tr><tr><td class="linenum"><pre>50</pre></td><td class="linenum"></td><td><pre>        print("Qbert is on row %d block %d" % self.pyramid_coordinates())</pre></td></tr><tr><td class="linenum"><pre>51</pre></td><td class="linenum"></td><td><pre></pre></td></tr></tbody><tbody class="diff-unch"><tr><td class="linenum"><pre>52</pre></td><td class="linenum"><pre>48</pre></td><td><pre>    def jump(self, x_speed, y_speed, costume):</pre></td></tr><tr><td class="linenum"><pre>53</pre></td><td class="linenum"><pre>49</pre></td><td><pre>        if self.jumping:</pre></td></tr><tr><td class="linenum"><pre>54</pre></td><td class="linenum"><pre>50</pre></td><td><pre>            return</pre></td></tr></tbody></table></div></div></div><div class="chapter-content"><h2>Make Q*bert fall off the pyramid</h2><p>Now we know what row and block Q*bert is on, it's easy to tell
whether they are actually on the pyramid or not.  If the row number is
smaller than zero then Q*bert has fallen off the bottom.  If the row
number is seven or more, then Q*bert has fallen off the top.  If
the block number is less than zero, then Q*bert has fallen off to the
left.</p><p>The only slightly tricky one is telling whether Q*bert has fallen off
to the right.  This happens if the block number (which starts at
<em>zero</em> for the left-most block, remember) is equal to or greater than
the number of blocks in the row, which, as we worked out above, is
(7 − <em>r</em>).  We'll broadcast a message if Q*bert falls off
the pyramid at the end of their jump:</p><div class="patch-container" data-code-as-of-commit='import pytch


class Background(pytch.Stage):
    Backdrops = ["background.png"]


class Block(pytch.Sprite):
    Costumes = ["block-unlit.png", "block-lit.png"]

    @pytch.when_green_flag_clicked
    def create_pyramid(self):
        for r in range(7):
            for b in range(7 - r):
                block_x = -150 + (b * 56) + (r * 28)
                block_y = -145 + (r * 42)
                self.go_to_xy(block_x, block_y)
                pytch.create_clone_of(self)
        self.hide()
        pytch.broadcast("set-up-qbert")


class Qbert(pytch.Sprite):
    Costumes = ["qbert0.png", "qbert1.png", "qbert2.png", "qbert3.png"]

    @pytch.when_green_flag_clicked
    def start_hidden(self):
        self.hide()

    # This list must have exactly 14 entries.
    bounce = [6, 4, 2, 1, 0, 0, 0, 0, 0, 0, -1, -2, -4, -6]

    @pytch.when_I_receive("set-up-qbert")
    def go_to_starting_position(self):
        self.go_to_xy(-150 + 3 * 56, -145 + (6 * 42) + 28)
        self.switch_costume("qbert1")
        self.go_to_front_layer()
        self.show()
        self.jumping = False

    def pyramid_coordinates(self):
        y_on_stage = self.y_position
        pyramid_r = (y_on_stage + 145 - 28) / 42
        x_on_stage = self.x_position
        pyramid_b = (x_on_stage + 150 - pyramid_r * 28) / 56
        return (pyramid_r, pyramid_b)

    def jump(self, x_speed, y_speed, costume):
        if self.jumping:
            return
        self.jumping = True
        self.switch_costume(costume)
        for frame in range(14):
            self.change_x(x_speed)
            self.change_y(y_speed + self.bounce[frame])

        r, b = self.pyramid_coordinates()
        if r &lt; 0 or r &gt;= 7 or b &lt; 0 or b &gt;= (7 - r):
            pytch.broadcast("fall-off")

        self.jumping = False

    @pytch.when_key_pressed("ArrowUp")
    def jump_up(self):
        self.jump(2, 3, "qbert0")

    @pytch.when_key_pressed("ArrowDown")
    def jump_down(self):
        self.jump(-2, -3, "qbert2")

    @pytch.when_key_pressed("ArrowLeft")
    def jump_left(self):
        self.jump(-2, 3, "qbert3")

    @pytch.when_key_pressed("ArrowRight")
    def jump_right(self):
        self.jump(2, -3, "qbert1")
' data-slug="check-for-falling-off"><div class="patch"><table><tbody class="diff-unch"><tr><td class="linenum"><pre>53</pre></td><td class="linenum"><pre>53</pre></td><td><pre>        for frame in range(14):</pre></td></tr><tr><td class="linenum"><pre>54</pre></td><td class="linenum"><pre>54</pre></td><td><pre>            self.change_x(x_speed)</pre></td></tr><tr><td class="linenum"><pre>55</pre></td><td class="linenum"><pre>55</pre></td><td><pre>            self.change_y(y_speed + self.bounce[frame])</pre></td></tr></tbody><tbody class="diff-add" data-added-text='
        r, b = self.pyramid_coordinates()
        if r &lt; 0 or r &gt;= 7 or b &lt; 0 or b &gt;= (7 - r):
            pytch.broadcast("fall-off")

'><tr><td class="linenum"></td><td class="linenum"><pre>56</pre></td><td><pre></pre></td></tr><tr><td class="linenum"></td><td class="linenum"><pre>57</pre></td><td><pre>        r, b = self.pyramid_coordinates()</pre></td></tr><tr><td class="linenum"></td><td class="linenum"><pre>58</pre></td><td><pre>        if r &lt; 0 or r &gt;= 7 or b &lt; 0 or b &gt;= (7 - r):</pre></td></tr><tr><td class="linenum"></td><td class="linenum"><pre>59</pre></td><td><pre>            pytch.broadcast("fall-off")</pre></td></tr><tr><td class="linenum"></td><td class="linenum"><pre>60</pre></td><td><pre></pre></td></tr></tbody><tbody class="diff-unch"><tr><td class="linenum"><pre>56</pre></td><td class="linenum"><pre>61</pre></td><td><pre>        self.jumping = False</pre></td></tr><tr><td class="linenum"><pre>57</pre></td><td class="linenum"><pre>62</pre></td><td><pre></pre></td></tr><tr><td class="linenum"><pre>58</pre></td><td class="linenum"><pre>63</pre></td><td><pre>    @pytch.when_key_pressed("ArrowUp")</pre></td></tr></tbody></table></div></div><p>If Q*bert falls off, we'll make it so they disappear into the
distance, by shrinking and then hiding altogether.  Here we're using a
version of the Python <code>range()</code> function where we give the starting
value as a percentage (here, 100), the stopping value as a percentage
(here, 10), and the 'step', which here has to be negative to work down
from 100 to 10 in steps of 5.  (In fact, Python stops just <em>before</em>
the 'stop' value, but this will look fine for our use.)  In the loop,
we'll turn the percentage into a value by dividing by 100.</p><div class="patch-container" data-code-as-of-commit='import pytch


class Background(pytch.Stage):
    Backdrops = ["background.png"]


class Block(pytch.Sprite):
    Costumes = ["block-unlit.png", "block-lit.png"]

    @pytch.when_green_flag_clicked
    def create_pyramid(self):
        for r in range(7):
            for b in range(7 - r):
                block_x = -150 + (b * 56) + (r * 28)
                block_y = -145 + (r * 42)
                self.go_to_xy(block_x, block_y)
                pytch.create_clone_of(self)
        self.hide()
        pytch.broadcast("set-up-qbert")


class Qbert(pytch.Sprite):
    Costumes = ["qbert0.png", "qbert1.png", "qbert2.png", "qbert3.png"]

    @pytch.when_green_flag_clicked
    def start_hidden(self):
        self.hide()

    # This list must have exactly 14 entries.
    bounce = [6, 4, 2, 1, 0, 0, 0, 0, 0, 0, -1, -2, -4, -6]

    @pytch.when_I_receive("set-up-qbert")
    def go_to_starting_position(self):
        self.go_to_xy(-150 + 3 * 56, -145 + (6 * 42) + 28)
        self.switch_costume("qbert1")
        self.go_to_front_layer()
        self.show()
        self.jumping = False

    def pyramid_coordinates(self):
        y_on_stage = self.y_position
        pyramid_r = (y_on_stage + 145 - 28) / 42
        x_on_stage = self.x_position
        pyramid_b = (x_on_stage + 150 - pyramid_r * 28) / 56
        return (pyramid_r, pyramid_b)

    def jump(self, x_speed, y_speed, costume):
        if self.jumping:
            return
        self.jumping = True
        self.switch_costume(costume)
        for frame in range(14):
            self.change_x(x_speed)
            self.change_y(y_speed + self.bounce[frame])

        r, b = self.pyramid_coordinates()
        if r &lt; 0 or r &gt;= 7 or b &lt; 0 or b &gt;= (7 - r):
            pytch.broadcast("fall-off")

        self.jumping = False

    @pytch.when_I_receive("fall-off")
    def disappear(self):
        for i in range(100, 10, -5):
            self.set_size(i / 100.0)
        self.hide()

    @pytch.when_key_pressed("ArrowUp")
    def jump_up(self):
        self.jump(2, 3, "qbert0")

    @pytch.when_key_pressed("ArrowDown")
    def jump_down(self):
        self.jump(-2, -3, "qbert2")

    @pytch.when_key_pressed("ArrowLeft")
    def jump_left(self):
        self.jump(-2, 3, "qbert3")

    @pytch.when_key_pressed("ArrowRight")
    def jump_right(self):
        self.jump(2, -3, "qbert1")
' data-slug="define-disappear-method"><div class="patch"><table><tbody class="diff-unch"><tr><td class="linenum"><pre>60</pre></td><td class="linenum"><pre>60</pre></td><td><pre></pre></td></tr><tr><td class="linenum"><pre>61</pre></td><td class="linenum"><pre>61</pre></td><td><pre>        self.jumping = False</pre></td></tr><tr><td class="linenum"><pre>62</pre></td><td class="linenum"><pre>62</pre></td><td><pre></pre></td></tr></tbody><tbody class="diff-add" data-added-text='    @pytch.when_I_receive("fall-off")
    def disappear(self):
        for i in range(100, 10, -5):
            self.set_size(i / 100.0)
        self.hide()

'><tr><td class="linenum"></td><td class="linenum"><pre>63</pre></td><td><pre>    @pytch.when_I_receive("fall-off")</pre></td></tr><tr><td class="linenum"></td><td class="linenum"><pre>64</pre></td><td><pre>    def disappear(self):</pre></td></tr><tr><td class="linenum"></td><td class="linenum"><pre>65</pre></td><td><pre>        for i in range(100, 10, -5):</pre></td></tr><tr><td class="linenum"></td><td class="linenum"><pre>66</pre></td><td><pre>            self.set_size(i / 100.0)</pre></td></tr><tr><td class="linenum"></td><td class="linenum"><pre>67</pre></td><td><pre>        self.hide()</pre></td></tr><tr><td class="linenum"></td><td class="linenum"><pre>68</pre></td><td><pre></pre></td></tr></tbody><tbody class="diff-unch"><tr><td class="linenum"><pre>63</pre></td><td class="linenum"><pre>69</pre></td><td><pre>    @pytch.when_key_pressed("ArrowUp")</pre></td></tr><tr><td class="linenum"><pre>64</pre></td><td class="linenum"><pre>70</pre></td><td><pre>    def jump_up(self):</pre></td></tr><tr><td class="linenum"><pre>65</pre></td><td class="linenum"><pre>71</pre></td><td><pre>        self.jump(2, 3, "qbert0")</pre></td></tr></tbody></table></div></div><p>If you try this now, you'll see that you can still jump around in a
strange way while falling off.  We can fix this by pretending that
Q*bert is still jumping.  We'll only set the <code>jumping</code> variable to
<code>False</code> if Q*bert <em>didn't</em> fall off, by moving that assignment into
an <code>else</code>:</p><div class="patch-container" data-code-as-of-commit='import pytch


class Background(pytch.Stage):
    Backdrops = ["background.png"]


class Block(pytch.Sprite):
    Costumes = ["block-unlit.png", "block-lit.png"]

    @pytch.when_green_flag_clicked
    def create_pyramid(self):
        for r in range(7):
            for b in range(7 - r):
                block_x = -150 + (b * 56) + (r * 28)
                block_y = -145 + (r * 42)
                self.go_to_xy(block_x, block_y)
                pytch.create_clone_of(self)
        self.hide()
        pytch.broadcast("set-up-qbert")


class Qbert(pytch.Sprite):
    Costumes = ["qbert0.png", "qbert1.png", "qbert2.png", "qbert3.png"]

    @pytch.when_green_flag_clicked
    def start_hidden(self):
        self.hide()

    # This list must have exactly 14 entries.
    bounce = [6, 4, 2, 1, 0, 0, 0, 0, 0, 0, -1, -2, -4, -6]

    @pytch.when_I_receive("set-up-qbert")
    def go_to_starting_position(self):
        self.go_to_xy(-150 + 3 * 56, -145 + (6 * 42) + 28)
        self.switch_costume("qbert1")
        self.go_to_front_layer()
        self.show()
        self.jumping = False

    def pyramid_coordinates(self):
        y_on_stage = self.y_position
        pyramid_r = (y_on_stage + 145 - 28) / 42
        x_on_stage = self.x_position
        pyramid_b = (x_on_stage + 150 - pyramid_r * 28) / 56
        return (pyramid_r, pyramid_b)

    def jump(self, x_speed, y_speed, costume):
        if self.jumping:
            return
        self.jumping = True
        self.switch_costume(costume)
        for frame in range(14):
            self.change_x(x_speed)
            self.change_y(y_speed + self.bounce[frame])

        r, b = self.pyramid_coordinates()
        if r &lt; 0 or r &gt;= 7 or b &lt; 0 or b &gt;= (7 - r):
            pytch.broadcast("fall-off")
        else:
            self.jumping = False

    @pytch.when_I_receive("fall-off")
    def disappear(self):
        for i in range(100, 10, -5):
            self.set_size(i / 100.0)
        self.hide()

    @pytch.when_key_pressed("ArrowUp")
    def jump_up(self):
        self.jump(2, 3, "qbert0")

    @pytch.when_key_pressed("ArrowDown")
    def jump_down(self):
        self.jump(-2, -3, "qbert2")

    @pytch.when_key_pressed("ArrowLeft")
    def jump_left(self):
        self.jump(-2, 3, "qbert3")

    @pytch.when_key_pressed("ArrowRight")
    def jump_right(self):
        self.jump(2, -3, "qbert1")
' data-slug="only-record-jump-finished-if-not-fallen-off"><div class="patch"><table><tbody class="diff-unch"><tr><td class="linenum"><pre>57</pre></td><td class="linenum"><pre>57</pre></td><td><pre>        r, b = self.pyramid_coordinates()</pre></td></tr><tr><td class="linenum"><pre>58</pre></td><td class="linenum"><pre>58</pre></td><td><pre>        if r &lt; 0 or r &gt;= 7 or b &lt; 0 or b &gt;= (7 - r):</pre></td></tr><tr><td class="linenum"><pre>59</pre></td><td class="linenum"><pre>59</pre></td><td><pre>            pytch.broadcast("fall-off")</pre></td></tr></tbody><tbody class="diff-del"><tr><td class="linenum"><pre>60</pre></td><td class="linenum"></td><td><pre></pre></td></tr><tr><td class="linenum"><pre>61</pre></td><td class="linenum"></td><td><pre>        self.jumping = False</pre></td></tr></tbody><tbody class="diff-add" data-added-text="        else:
            self.jumping = False
"><tr><td class="linenum"></td><td class="linenum"><pre>60</pre></td><td><pre>        else:</pre></td></tr><tr><td class="linenum"></td><td class="linenum"><pre>61</pre></td><td><pre>            self.jumping = False</pre></td></tr></tbody><tbody class="diff-unch"><tr><td class="linenum"><pre>62</pre></td><td class="linenum"><pre>62</pre></td><td><pre></pre></td></tr><tr><td class="linenum"><pre>63</pre></td><td class="linenum"><pre>63</pre></td><td><pre>    @pytch.when_I_receive("fall-off")</pre></td></tr><tr><td class="linenum"><pre>64</pre></td><td class="linenum"><pre>64</pre></td><td><pre>    def disappear(self):</pre></td></tr></tbody></table></div></div></div><div class="chapter-content"><h2>Lighting up the blocks Q*bert lands on</h2><p>Since the block is the actor which is going to need to do something
when it's landed on, we'll do this work in the <em>Block</em> class.  We're
going to define a method which checks whether the clone's position is
equal to Q*bert's.  If it is, that block has been landed on and
should switch to the lit-up costume.</p><p>But first, we need to make each <em>Block</em> clone know its own position.
We'll set new instance variables in the original <em>Block</em> just before
making the clone:</p><div class="patch-container" data-code-as-of-commit='import pytch


class Background(pytch.Stage):
    Backdrops = ["background.png"]


class Block(pytch.Sprite):
    Costumes = ["block-unlit.png", "block-lit.png"]

    @pytch.when_green_flag_clicked
    def create_pyramid(self):
        for r in range(7):
            for b in range(7 - r):
                block_x = -150 + (b * 56) + (r * 28)
                block_y = -145 + (r * 42)
                self.go_to_xy(block_x, block_y)
                self.pyramid_r = r
                self.pyramid_b = b
                pytch.create_clone_of(self)
        self.hide()
        pytch.broadcast("set-up-qbert")


class Qbert(pytch.Sprite):
    Costumes = ["qbert0.png", "qbert1.png", "qbert2.png", "qbert3.png"]

    @pytch.when_green_flag_clicked
    def start_hidden(self):
        self.hide()

    # This list must have exactly 14 entries.
    bounce = [6, 4, 2, 1, 0, 0, 0, 0, 0, 0, -1, -2, -4, -6]

    @pytch.when_I_receive("set-up-qbert")
    def go_to_starting_position(self):
        self.go_to_xy(-150 + 3 * 56, -145 + (6 * 42) + 28)
        self.switch_costume("qbert1")
        self.go_to_front_layer()
        self.show()
        self.jumping = False

    def pyramid_coordinates(self):
        y_on_stage = self.y_position
        pyramid_r = (y_on_stage + 145 - 28) / 42
        x_on_stage = self.x_position
        pyramid_b = (x_on_stage + 150 - pyramid_r * 28) / 56
        return (pyramid_r, pyramid_b)

    def jump(self, x_speed, y_speed, costume):
        if self.jumping:
            return
        self.jumping = True
        self.switch_costume(costume)
        for frame in range(14):
            self.change_x(x_speed)
            self.change_y(y_speed + self.bounce[frame])

        r, b = self.pyramid_coordinates()
        if r &lt; 0 or r &gt;= 7 or b &lt; 0 or b &gt;= (7 - r):
            pytch.broadcast("fall-off")
        else:
            self.jumping = False

    @pytch.when_I_receive("fall-off")
    def disappear(self):
        for i in range(100, 10, -5):
            self.set_size(i / 100.0)
        self.hide()

    @pytch.when_key_pressed("ArrowUp")
    def jump_up(self):
        self.jump(2, 3, "qbert0")

    @pytch.when_key_pressed("ArrowDown")
    def jump_down(self):
        self.jump(-2, -3, "qbert2")

    @pytch.when_key_pressed("ArrowLeft")
    def jump_left(self):
        self.jump(-2, 3, "qbert3")

    @pytch.when_key_pressed("ArrowRight")
    def jump_right(self):
        self.jump(2, -3, "qbert1")
' data-slug="record-row-block-for-clone"><div class="patch"><table><tbody class="diff-unch"><tr><td class="linenum"><pre>15</pre></td><td class="linenum"><pre>15</pre></td><td><pre>                block_x = -150 + (b * 56) + (r * 28)</pre></td></tr><tr><td class="linenum"><pre>16</pre></td><td class="linenum"><pre>16</pre></td><td><pre>                block_y = -145 + (r * 42)</pre></td></tr><tr><td class="linenum"><pre>17</pre></td><td class="linenum"><pre>17</pre></td><td><pre>                self.go_to_xy(block_x, block_y)</pre></td></tr></tbody><tbody class="diff-add" data-added-text="                self.pyramid_r = r
                self.pyramid_b = b
"><tr><td class="linenum"></td><td class="linenum"><pre>18</pre></td><td><pre>                self.pyramid_r = r</pre></td></tr><tr><td class="linenum"></td><td class="linenum"><pre>19</pre></td><td><pre>                self.pyramid_b = b</pre></td></tr></tbody><tbody class="diff-unch"><tr><td class="linenum"><pre>18</pre></td><td class="linenum"><pre>20</pre></td><td><pre>                pytch.create_clone_of(self)</pre></td></tr><tr><td class="linenum"><pre>19</pre></td><td class="linenum"><pre>21</pre></td><td><pre>        self.hide()</pre></td></tr><tr><td class="linenum"><pre>20</pre></td><td class="linenum"><pre>22</pre></td><td><pre>        pytch.broadcast("set-up-qbert")</pre></td></tr></tbody></table></div></div><p>Now each <em>Block</em> clone has this information, we can define a method
which tests whether that <em>Block</em> is the one Q*bert is on.  We'll find
the original (in fact, only) Q*bert instance, and ask it for its
coordinates in pyramid row/block terms, then check whether the Block's
row-number and block-number match.  If so, light up!</p><div class="patch-container" data-code-as-of-commit='import pytch


class Background(pytch.Stage):
    Backdrops = ["background.png"]


class Block(pytch.Sprite):
    Costumes = ["block-unlit.png", "block-lit.png"]

    @pytch.when_green_flag_clicked
    def create_pyramid(self):
        for r in range(7):
            for b in range(7 - r):
                block_x = -150 + (b * 56) + (r * 28)
                block_y = -145 + (r * 42)
                self.go_to_xy(block_x, block_y)
                self.pyramid_r = r
                self.pyramid_b = b
                pytch.create_clone_of(self)
        self.hide()
        pytch.broadcast("set-up-qbert")

    @pytch.when_I_receive("check-block")
    def check_whether_landed_on(self):
        qbert_r, qbert_b = Qbert.the_original().pyramid_coordinates()
        if self.pyramid_r == qbert_r and self.pyramid_b == qbert_b:
            self.switch_costume("block-lit")


class Qbert(pytch.Sprite):
    Costumes = ["qbert0.png", "qbert1.png", "qbert2.png", "qbert3.png"]

    @pytch.when_green_flag_clicked
    def start_hidden(self):
        self.hide()

    # This list must have exactly 14 entries.
    bounce = [6, 4, 2, 1, 0, 0, 0, 0, 0, 0, -1, -2, -4, -6]

    @pytch.when_I_receive("set-up-qbert")
    def go_to_starting_position(self):
        self.go_to_xy(-150 + 3 * 56, -145 + (6 * 42) + 28)
        self.switch_costume("qbert1")
        self.go_to_front_layer()
        self.show()
        self.jumping = False

    def pyramid_coordinates(self):
        y_on_stage = self.y_position
        pyramid_r = (y_on_stage + 145 - 28) / 42
        x_on_stage = self.x_position
        pyramid_b = (x_on_stage + 150 - pyramid_r * 28) / 56
        return (pyramid_r, pyramid_b)

    def jump(self, x_speed, y_speed, costume):
        if self.jumping:
            return
        self.jumping = True
        self.switch_costume(costume)
        for frame in range(14):
            self.change_x(x_speed)
            self.change_y(y_speed + self.bounce[frame])

        r, b = self.pyramid_coordinates()
        if r &lt; 0 or r &gt;= 7 or b &lt; 0 or b &gt;= (7 - r):
            pytch.broadcast("fall-off")
        else:
            self.jumping = False

    @pytch.when_I_receive("fall-off")
    def disappear(self):
        for i in range(100, 10, -5):
            self.set_size(i / 100.0)
        self.hide()

    @pytch.when_key_pressed("ArrowUp")
    def jump_up(self):
        self.jump(2, 3, "qbert0")

    @pytch.when_key_pressed("ArrowDown")
    def jump_down(self):
        self.jump(-2, -3, "qbert2")

    @pytch.when_key_pressed("ArrowLeft")
    def jump_left(self):
        self.jump(-2, 3, "qbert3")

    @pytch.when_key_pressed("ArrowRight")
    def jump_right(self):
        self.jump(2, -3, "qbert1")
' data-slug="define-Block-check-landed-on-method"><div class="patch"><table><tbody class="diff-unch"><tr><td class="linenum"><pre>21</pre></td><td class="linenum"><pre>21</pre></td><td><pre>        self.hide()</pre></td></tr><tr><td class="linenum"><pre>22</pre></td><td class="linenum"><pre>22</pre></td><td><pre>        pytch.broadcast("set-up-qbert")</pre></td></tr><tr><td class="linenum"><pre>23</pre></td><td class="linenum"><pre>23</pre></td><td><pre></pre></td></tr></tbody><tbody class="diff-add" data-added-text='    @pytch.when_I_receive("check-block")
    def check_whether_landed_on(self):
        qbert_r, qbert_b = Qbert.the_original().pyramid_coordinates()
        if self.pyramid_r == qbert_r and self.pyramid_b == qbert_b:
            self.switch_costume("block-lit")

'><tr><td class="linenum"></td><td class="linenum"><pre>24</pre></td><td><pre>    @pytch.when_I_receive("check-block")</pre></td></tr><tr><td class="linenum"></td><td class="linenum"><pre>25</pre></td><td><pre>    def check_whether_landed_on(self):</pre></td></tr><tr><td class="linenum"></td><td class="linenum"><pre>26</pre></td><td><pre>        qbert_r, qbert_b = Qbert.the_original().pyramid_coordinates()</pre></td></tr><tr><td class="linenum"></td><td class="linenum"><pre>27</pre></td><td><pre>        if self.pyramid_r == qbert_r and self.pyramid_b == qbert_b:</pre></td></tr><tr><td class="linenum"></td><td class="linenum"><pre>28</pre></td><td><pre>            self.switch_costume("block-lit")</pre></td></tr><tr><td class="linenum"></td><td class="linenum"><pre>29</pre></td><td><pre></pre></td></tr></tbody><tbody class="diff-unch"><tr><td class="linenum"><pre>24</pre></td><td class="linenum"><pre>30</pre></td><td><pre></pre></td></tr><tr><td class="linenum"><pre>25</pre></td><td class="linenum"><pre>31</pre></td><td><pre>class Qbert(pytch.Sprite):</pre></td></tr><tr><td class="linenum"><pre>26</pre></td><td class="linenum"><pre>32</pre></td><td><pre>    Costumes = ["qbert0.png", "qbert1.png", "qbert2.png", "qbert3.png"]</pre></td></tr></tbody></table></div></div><p>All we need to do now is launch this method by making Q*bert
broadcast the message:</p><div class="patch-container" data-code-as-of-commit='import pytch


class Background(pytch.Stage):
    Backdrops = ["background.png"]


class Block(pytch.Sprite):
    Costumes = ["block-unlit.png", "block-lit.png"]

    @pytch.when_green_flag_clicked
    def create_pyramid(self):
        for r in range(7):
            for b in range(7 - r):
                block_x = -150 + (b * 56) + (r * 28)
                block_y = -145 + (r * 42)
                self.go_to_xy(block_x, block_y)
                self.pyramid_r = r
                self.pyramid_b = b
                pytch.create_clone_of(self)
        self.hide()
        pytch.broadcast("set-up-qbert")

    @pytch.when_I_receive("check-block")
    def check_whether_landed_on(self):
        qbert_r, qbert_b = Qbert.the_original().pyramid_coordinates()
        if self.pyramid_r == qbert_r and self.pyramid_b == qbert_b:
            self.switch_costume("block-lit")


class Qbert(pytch.Sprite):
    Costumes = ["qbert0.png", "qbert1.png", "qbert2.png", "qbert3.png"]

    @pytch.when_green_flag_clicked
    def start_hidden(self):
        self.hide()

    # This list must have exactly 14 entries.
    bounce = [6, 4, 2, 1, 0, 0, 0, 0, 0, 0, -1, -2, -4, -6]

    @pytch.when_I_receive("set-up-qbert")
    def go_to_starting_position(self):
        self.go_to_xy(-150 + 3 * 56, -145 + (6 * 42) + 28)
        self.switch_costume("qbert1")
        self.go_to_front_layer()
        self.show()
        self.jumping = False

    def pyramid_coordinates(self):
        y_on_stage = self.y_position
        pyramid_r = (y_on_stage + 145 - 28) / 42
        x_on_stage = self.x_position
        pyramid_b = (x_on_stage + 150 - pyramid_r * 28) / 56
        return (pyramid_r, pyramid_b)

    def jump(self, x_speed, y_speed, costume):
        if self.jumping:
            return
        self.jumping = True
        self.switch_costume(costume)
        for frame in range(14):
            self.change_x(x_speed)
            self.change_y(y_speed + self.bounce[frame])

        r, b = self.pyramid_coordinates()
        if r &lt; 0 or r &gt;= 7 or b &lt; 0 or b &gt;= (7 - r):
            pytch.broadcast("fall-off")
        else:
            pytch.broadcast_and_wait("check-block")
            self.jumping = False

    @pytch.when_I_receive("fall-off")
    def disappear(self):
        for i in range(100, 10, -5):
            self.set_size(i / 100.0)
        self.hide()

    @pytch.when_key_pressed("ArrowUp")
    def jump_up(self):
        self.jump(2, 3, "qbert0")

    @pytch.when_key_pressed("ArrowDown")
    def jump_down(self):
        self.jump(-2, -3, "qbert2")

    @pytch.when_key_pressed("ArrowLeft")
    def jump_left(self):
        self.jump(-2, 3, "qbert3")

    @pytch.when_key_pressed("ArrowRight")
    def jump_right(self):
        self.jump(2, -3, "qbert1")
' data-slug="check-block-if-not-fallen-off"><div class="patch"><table><tbody class="diff-unch"><tr><td class="linenum"><pre>66</pre></td><td class="linenum"><pre>66</pre></td><td><pre>        if r &lt; 0 or r &gt;= 7 or b &lt; 0 or b &gt;= (7 - r):</pre></td></tr><tr><td class="linenum"><pre>67</pre></td><td class="linenum"><pre>67</pre></td><td><pre>            pytch.broadcast("fall-off")</pre></td></tr><tr><td class="linenum"><pre>68</pre></td><td class="linenum"><pre>68</pre></td><td><pre>        else:</pre></td></tr></tbody><tbody class="diff-add" data-added-text='            pytch.broadcast_and_wait("check-block")
'><tr><td class="linenum"></td><td class="linenum"><pre>69</pre></td><td><pre>            pytch.broadcast_and_wait("check-block")</pre></td></tr></tbody><tbody class="diff-unch"><tr><td class="linenum"><pre>69</pre></td><td class="linenum"><pre>70</pre></td><td><pre>            self.jumping = False</pre></td></tr><tr><td class="linenum"><pre>70</pre></td><td class="linenum"><pre>71</pre></td><td><pre></pre></td></tr><tr><td class="linenum"><pre>71</pre></td><td class="linenum"><pre>72</pre></td><td><pre>    @pytch.when_I_receive("fall-off")</pre></td></tr></tbody></table></div></div><p>We use <code>broadcast_and_wait()</code> to make sure the block checking has
happened before allowing Q*bert to move again.</p></div><div class="chapter-content"><h2>Checking Q*bert's progress</h2><p>This is now working quite well, but we need a way to tell whether
Q*bert has cleared the level.  We'll track the number of un-lit-up
blocks Q*bert still has left to jump on.  We'll store this number in
a <em>global variable</em>, which is one that all sprites have access to.  We
define it at the start of the code, outside any <code>class</code>:</p><div class="patch-container" data-code-as-of-commit='import pytch


blocks_left = 0


class Background(pytch.Stage):
    Backdrops = ["background.png"]


class Block(pytch.Sprite):
    Costumes = ["block-unlit.png", "block-lit.png"]

    @pytch.when_green_flag_clicked
    def create_pyramid(self):
        for r in range(7):
            for b in range(7 - r):
                block_x = -150 + (b * 56) + (r * 28)
                block_y = -145 + (r * 42)
                self.go_to_xy(block_x, block_y)
                self.pyramid_r = r
                self.pyramid_b = b
                pytch.create_clone_of(self)
        self.hide()
        pytch.broadcast("set-up-qbert")

    @pytch.when_I_receive("check-block")
    def check_whether_landed_on(self):
        qbert_r, qbert_b = Qbert.the_original().pyramid_coordinates()
        if self.pyramid_r == qbert_r and self.pyramid_b == qbert_b:
            self.switch_costume("block-lit")


class Qbert(pytch.Sprite):
    Costumes = ["qbert0.png", "qbert1.png", "qbert2.png", "qbert3.png"]

    @pytch.when_green_flag_clicked
    def start_hidden(self):
        self.hide()

    # This list must have exactly 14 entries.
    bounce = [6, 4, 2, 1, 0, 0, 0, 0, 0, 0, -1, -2, -4, -6]

    @pytch.when_I_receive("set-up-qbert")
    def go_to_starting_position(self):
        self.go_to_xy(-150 + 3 * 56, -145 + (6 * 42) + 28)
        self.switch_costume("qbert1")
        self.go_to_front_layer()
        self.show()
        self.jumping = False

    def pyramid_coordinates(self):
        y_on_stage = self.y_position
        pyramid_r = (y_on_stage + 145 - 28) / 42
        x_on_stage = self.x_position
        pyramid_b = (x_on_stage + 150 - pyramid_r * 28) / 56
        return (pyramid_r, pyramid_b)

    def jump(self, x_speed, y_speed, costume):
        if self.jumping:
            return
        self.jumping = True
        self.switch_costume(costume)
        for frame in range(14):
            self.change_x(x_speed)
            self.change_y(y_speed + self.bounce[frame])

        r, b = self.pyramid_coordinates()
        if r &lt; 0 or r &gt;= 7 or b &lt; 0 or b &gt;= (7 - r):
            pytch.broadcast("fall-off")
        else:
            pytch.broadcast_and_wait("check-block")
            self.jumping = False

    @pytch.when_I_receive("fall-off")
    def disappear(self):
        for i in range(100, 10, -5):
            self.set_size(i / 100.0)
        self.hide()

    @pytch.when_key_pressed("ArrowUp")
    def jump_up(self):
        self.jump(2, 3, "qbert0")

    @pytch.when_key_pressed("ArrowDown")
    def jump_down(self):
        self.jump(-2, -3, "qbert2")

    @pytch.when_key_pressed("ArrowLeft")
    def jump_left(self):
        self.jump(-2, 3, "qbert3")

    @pytch.when_key_pressed("ArrowRight")
    def jump_right(self):
        self.jump(2, -3, "qbert1")
' data-slug="initialise-blocks-left-counter"><div class="patch"><table><tbody class="diff-unch"><tr><td class="linenum"><pre>1</pre></td><td class="linenum"><pre>1</pre></td><td><pre>import pytch</pre></td></tr><tr><td class="linenum"><pre>2</pre></td><td class="linenum"><pre>2</pre></td><td><pre></pre></td></tr><tr><td class="linenum"><pre>3</pre></td><td class="linenum"><pre>3</pre></td><td><pre></pre></td></tr></tbody><tbody class="diff-add" data-added-text="blocks_left = 0


"><tr><td class="linenum"></td><td class="linenum"><pre>4</pre></td><td><pre>blocks_left = 0</pre></td></tr><tr><td class="linenum"></td><td class="linenum"><pre>5</pre></td><td><pre></pre></td></tr><tr><td class="linenum"></td><td class="linenum"><pre>6</pre></td><td><pre></pre></td></tr></tbody><tbody class="diff-unch"><tr><td class="linenum"><pre>4</pre></td><td class="linenum"><pre>7</pre></td><td><pre>class Background(pytch.Stage):</pre></td></tr><tr><td class="linenum"><pre>5</pre></td><td class="linenum"><pre>8</pre></td><td><pre>    Backdrops = ["background.png"]</pre></td></tr><tr><td class="linenum"><pre>6</pre></td><td class="linenum"><pre>9</pre></td><td><pre></pre></td></tr></tbody></table></div></div><p>This might look strange, since at the start of the game there are
definitely <em>not</em> zero un-lit-up blocks.  What we'll do is make Q*bert
count the blocks as soon as the pyramid has been made:</p><div class="patch-container" data-code-as-of-commit='import pytch


blocks_left = 0


class Background(pytch.Stage):
    Backdrops = ["background.png"]


class Block(pytch.Sprite):
    Costumes = ["block-unlit.png", "block-lit.png"]

    @pytch.when_green_flag_clicked
    def create_pyramid(self):
        for r in range(7):
            for b in range(7 - r):
                block_x = -150 + (b * 56) + (r * 28)
                block_y = -145 + (r * 42)
                self.go_to_xy(block_x, block_y)
                self.pyramid_r = r
                self.pyramid_b = b
                pytch.create_clone_of(self)
        self.hide()
        pytch.broadcast("set-up-qbert")

    @pytch.when_I_receive("check-block")
    def check_whether_landed_on(self):
        qbert_r, qbert_b = Qbert.the_original().pyramid_coordinates()
        if self.pyramid_r == qbert_r and self.pyramid_b == qbert_b:
            self.switch_costume("block-lit")


class Qbert(pytch.Sprite):
    Costumes = ["qbert0.png", "qbert1.png", "qbert2.png", "qbert3.png"]

    @pytch.when_green_flag_clicked
    def start_hidden(self):
        self.hide()

    # This list must have exactly 14 entries.
    bounce = [6, 4, 2, 1, 0, 0, 0, 0, 0, 0, -1, -2, -4, -6]

    @pytch.when_I_receive("set-up-qbert")
    def go_to_starting_position(self):
        self.go_to_xy(-150 + 3 * 56, -145 + (6 * 42) + 28)
        self.switch_costume("qbert1")
        self.go_to_front_layer()
        self.show()
        self.jumping = False
        global blocks_left
        blocks_left = len(Block.all_clones())

    def pyramid_coordinates(self):
        y_on_stage = self.y_position
        pyramid_r = (y_on_stage + 145 - 28) / 42
        x_on_stage = self.x_position
        pyramid_b = (x_on_stage + 150 - pyramid_r * 28) / 56
        return (pyramid_r, pyramid_b)

    def jump(self, x_speed, y_speed, costume):
        if self.jumping:
            return
        self.jumping = True
        self.switch_costume(costume)
        for frame in range(14):
            self.change_x(x_speed)
            self.change_y(y_speed + self.bounce[frame])

        r, b = self.pyramid_coordinates()
        if r &lt; 0 or r &gt;= 7 or b &lt; 0 or b &gt;= (7 - r):
            pytch.broadcast("fall-off")
        else:
            pytch.broadcast_and_wait("check-block")
            self.jumping = False

    @pytch.when_I_receive("fall-off")
    def disappear(self):
        for i in range(100, 10, -5):
            self.set_size(i / 100.0)
        self.hide()

    @pytch.when_key_pressed("ArrowUp")
    def jump_up(self):
        self.jump(2, 3, "qbert0")

    @pytch.when_key_pressed("ArrowDown")
    def jump_down(self):
        self.jump(-2, -3, "qbert2")

    @pytch.when_key_pressed("ArrowLeft")
    def jump_left(self):
        self.jump(-2, 3, "qbert3")

    @pytch.when_key_pressed("ArrowRight")
    def jump_right(self):
        self.jump(2, -3, "qbert1")
' data-slug="count-initial-number-blocks-left"><div class="patch"><table><tbody class="diff-unch"><tr><td class="linenum"><pre>48</pre></td><td class="linenum"><pre>48</pre></td><td><pre>        self.go_to_front_layer()</pre></td></tr><tr><td class="linenum"><pre>49</pre></td><td class="linenum"><pre>49</pre></td><td><pre>        self.show()</pre></td></tr><tr><td class="linenum"><pre>50</pre></td><td class="linenum"><pre>50</pre></td><td><pre>        self.jumping = False</pre></td></tr></tbody><tbody class="diff-add" data-added-text="        global blocks_left
        blocks_left = len(Block.all_clones())
"><tr><td class="linenum"></td><td class="linenum"><pre>51</pre></td><td><pre>        global blocks_left</pre></td></tr><tr><td class="linenum"></td><td class="linenum"><pre>52</pre></td><td><pre>        blocks_left = len(Block.all_clones())</pre></td></tr></tbody><tbody class="diff-unch"><tr><td class="linenum"><pre>51</pre></td><td class="linenum"><pre>53</pre></td><td><pre></pre></td></tr><tr><td class="linenum"><pre>52</pre></td><td class="linenum"><pre>54</pre></td><td><pre>    def pyramid_coordinates(self):</pre></td></tr><tr><td class="linenum"><pre>53</pre></td><td class="linenum"><pre>55</pre></td><td><pre>        y_on_stage = self.y_position</pre></td></tr></tbody></table></div></div><p>There are a couple of things to notice here:</p><ul>
<li>We need to tell Python that it's the global variable <code>blocks_left</code>
  we want to set the value of, not make a new local variable.</li>
<li>We use the <code>all_clones()</code> method on the <code>Block</code> <em>class</em>, which is a
  Pytch built-in giving us a list of all the live clones of that
  class.  We're only interested in how many clones there are, so we
  find the length of that list with the Python built-in <code>len()</code>.</li>
</ul><p>Now, when a block works out that it's the one Q*bert has landed on,
it will first test whether it's already lit up, by checking what
costume it's wearing.  Only if it's <em>not</em> already lit up do we switch
its costume to the lit-up one.</p><div class="patch-container" data-code-as-of-commit='import pytch


blocks_left = 0


class Background(pytch.Stage):
    Backdrops = ["background.png"]


class Block(pytch.Sprite):
    Costumes = ["block-unlit.png", "block-lit.png"]

    @pytch.when_green_flag_clicked
    def create_pyramid(self):
        for r in range(7):
            for b in range(7 - r):
                block_x = -150 + (b * 56) + (r * 28)
                block_y = -145 + (r * 42)
                self.go_to_xy(block_x, block_y)
                self.pyramid_r = r
                self.pyramid_b = b
                pytch.create_clone_of(self)
        self.hide()
        pytch.broadcast("set-up-qbert")

    @pytch.when_I_receive("check-block")
    def check_whether_landed_on(self):
        qbert_r, qbert_b = Qbert.the_original().pyramid_coordinates()
        if self.pyramid_r == qbert_r and self.pyramid_b == qbert_b:
            if self.costume_name == "block-unlit":
                self.switch_costume("block-lit")


class Qbert(pytch.Sprite):
    Costumes = ["qbert0.png", "qbert1.png", "qbert2.png", "qbert3.png"]

    @pytch.when_green_flag_clicked
    def start_hidden(self):
        self.hide()

    # This list must have exactly 14 entries.
    bounce = [6, 4, 2, 1, 0, 0, 0, 0, 0, 0, -1, -2, -4, -6]

    @pytch.when_I_receive("set-up-qbert")
    def go_to_starting_position(self):
        self.go_to_xy(-150 + 3 * 56, -145 + (6 * 42) + 28)
        self.switch_costume("qbert1")
        self.go_to_front_layer()
        self.show()
        self.jumping = False
        global blocks_left
        blocks_left = len(Block.all_clones())

    def pyramid_coordinates(self):
        y_on_stage = self.y_position
        pyramid_r = (y_on_stage + 145 - 28) / 42
        x_on_stage = self.x_position
        pyramid_b = (x_on_stage + 150 - pyramid_r * 28) / 56
        return (pyramid_r, pyramid_b)

    def jump(self, x_speed, y_speed, costume):
        if self.jumping:
            return
        self.jumping = True
        self.switch_costume(costume)
        for frame in range(14):
            self.change_x(x_speed)
            self.change_y(y_speed + self.bounce[frame])

        r, b = self.pyramid_coordinates()
        if r &lt; 0 or r &gt;= 7 or b &lt; 0 or b &gt;= (7 - r):
            pytch.broadcast("fall-off")
        else:
            pytch.broadcast_and_wait("check-block")
            self.jumping = False

    @pytch.when_I_receive("fall-off")
    def disappear(self):
        for i in range(100, 10, -5):
            self.set_size(i / 100.0)
        self.hide()

    @pytch.when_key_pressed("ArrowUp")
    def jump_up(self):
        self.jump(2, 3, "qbert0")

    @pytch.when_key_pressed("ArrowDown")
    def jump_down(self):
        self.jump(-2, -3, "qbert2")

    @pytch.when_key_pressed("ArrowLeft")
    def jump_left(self):
        self.jump(-2, 3, "qbert3")

    @pytch.when_key_pressed("ArrowRight")
    def jump_right(self):
        self.jump(2, -3, "qbert1")
' data-slug="only-light-up-if-not-already"><div class="patch"><table><tbody class="diff-unch"><tr><td class="linenum"><pre>28</pre></td><td class="linenum"><pre>28</pre></td><td><pre>    def check_whether_landed_on(self):</pre></td></tr><tr><td class="linenum"><pre>29</pre></td><td class="linenum"><pre>29</pre></td><td><pre>        qbert_r, qbert_b = Qbert.the_original().pyramid_coordinates()</pre></td></tr><tr><td class="linenum"><pre>30</pre></td><td class="linenum"><pre>30</pre></td><td><pre>        if self.pyramid_r == qbert_r and self.pyramid_b == qbert_b:</pre></td></tr></tbody><tbody class="diff-del"><tr><td class="linenum"><pre>31</pre></td><td class="linenum"></td><td><pre>            self.switch_costume("block-lit")</pre></td></tr></tbody><tbody class="diff-add" data-added-text='            if self.costume_name == "block-unlit":
                self.switch_costume("block-lit")
'><tr><td class="linenum"></td><td class="linenum"><pre>31</pre></td><td><pre>            if self.costume_name == "block-unlit":</pre></td></tr><tr><td class="linenum"></td><td class="linenum"><pre>32</pre></td><td><pre>                self.switch_costume("block-lit")</pre></td></tr></tbody><tbody class="diff-unch"><tr><td class="linenum"><pre>32</pre></td><td class="linenum"><pre>33</pre></td><td><pre></pre></td></tr><tr><td class="linenum"><pre>33</pre></td><td class="linenum"><pre>34</pre></td><td><pre></pre></td></tr><tr><td class="linenum"><pre>34</pre></td><td class="linenum"><pre>35</pre></td><td><pre>class Qbert(pytch.Sprite):</pre></td></tr></tbody></table></div></div><p>This small change hasn't made any difference, but we can now do the
other job required when a block goes from unlit to lit — we can
decrease by one the number of blocks left to light up.  Again, we have
to tell Python that it's the global <code>blocks_left</code> variable we want to
work with:</p><div class="patch-container" data-code-as-of-commit='import pytch


blocks_left = 0


class Background(pytch.Stage):
    Backdrops = ["background.png"]


class Block(pytch.Sprite):
    Costumes = ["block-unlit.png", "block-lit.png"]

    @pytch.when_green_flag_clicked
    def create_pyramid(self):
        for r in range(7):
            for b in range(7 - r):
                block_x = -150 + (b * 56) + (r * 28)
                block_y = -145 + (r * 42)
                self.go_to_xy(block_x, block_y)
                self.pyramid_r = r
                self.pyramid_b = b
                pytch.create_clone_of(self)
        self.hide()
        pytch.broadcast("set-up-qbert")

    @pytch.when_I_receive("check-block")
    def check_whether_landed_on(self):
        qbert_r, qbert_b = Qbert.the_original().pyramid_coordinates()
        if self.pyramid_r == qbert_r and self.pyramid_b == qbert_b:
            if self.costume_name == "block-unlit":
                self.switch_costume("block-lit")
                global blocks_left
                blocks_left -= 1


class Qbert(pytch.Sprite):
    Costumes = ["qbert0.png", "qbert1.png", "qbert2.png", "qbert3.png"]

    @pytch.when_green_flag_clicked
    def start_hidden(self):
        self.hide()

    # This list must have exactly 14 entries.
    bounce = [6, 4, 2, 1, 0, 0, 0, 0, 0, 0, -1, -2, -4, -6]

    @pytch.when_I_receive("set-up-qbert")
    def go_to_starting_position(self):
        self.go_to_xy(-150 + 3 * 56, -145 + (6 * 42) + 28)
        self.switch_costume("qbert1")
        self.go_to_front_layer()
        self.show()
        self.jumping = False
        global blocks_left
        blocks_left = len(Block.all_clones())

    def pyramid_coordinates(self):
        y_on_stage = self.y_position
        pyramid_r = (y_on_stage + 145 - 28) / 42
        x_on_stage = self.x_position
        pyramid_b = (x_on_stage + 150 - pyramid_r * 28) / 56
        return (pyramid_r, pyramid_b)

    def jump(self, x_speed, y_speed, costume):
        if self.jumping:
            return
        self.jumping = True
        self.switch_costume(costume)
        for frame in range(14):
            self.change_x(x_speed)
            self.change_y(y_speed + self.bounce[frame])

        r, b = self.pyramid_coordinates()
        if r &lt; 0 or r &gt;= 7 or b &lt; 0 or b &gt;= (7 - r):
            pytch.broadcast("fall-off")
        else:
            pytch.broadcast_and_wait("check-block")
            self.jumping = False

    @pytch.when_I_receive("fall-off")
    def disappear(self):
        for i in range(100, 10, -5):
            self.set_size(i / 100.0)
        self.hide()

    @pytch.when_key_pressed("ArrowUp")
    def jump_up(self):
        self.jump(2, 3, "qbert0")

    @pytch.when_key_pressed("ArrowDown")
    def jump_down(self):
        self.jump(-2, -3, "qbert2")

    @pytch.when_key_pressed("ArrowLeft")
    def jump_left(self):
        self.jump(-2, 3, "qbert3")

    @pytch.when_key_pressed("ArrowRight")
    def jump_right(self):
        self.jump(2, -3, "qbert1")
' data-slug="decrement-blocks-left-when-newly-lit-up"><div class="patch"><table><tbody class="diff-unch"><tr><td class="linenum"><pre>30</pre></td><td class="linenum"><pre>30</pre></td><td><pre>        if self.pyramid_r == qbert_r and self.pyramid_b == qbert_b:</pre></td></tr><tr><td class="linenum"><pre>31</pre></td><td class="linenum"><pre>31</pre></td><td><pre>            if self.costume_name == "block-unlit":</pre></td></tr><tr><td class="linenum"><pre>32</pre></td><td class="linenum"><pre>32</pre></td><td><pre>                self.switch_costume("block-lit")</pre></td></tr></tbody><tbody class="diff-add" data-added-text="                global blocks_left
                blocks_left -= 1
"><tr><td class="linenum"></td><td class="linenum"><pre>33</pre></td><td><pre>                global blocks_left</pre></td></tr><tr><td class="linenum"></td><td class="linenum"><pre>34</pre></td><td><pre>                blocks_left -= 1</pre></td></tr></tbody><tbody class="diff-unch"><tr><td class="linenum"><pre>33</pre></td><td class="linenum"><pre>35</pre></td><td><pre></pre></td></tr><tr><td class="linenum"><pre>34</pre></td><td class="linenum"><pre>36</pre></td><td><pre></pre></td></tr><tr><td class="linenum"><pre>35</pre></td><td class="linenum"><pre>37</pre></td><td><pre>class Qbert(pytch.Sprite):</pre></td></tr></tbody></table></div></div><p>To check this is working, we'll make Q*bert say the number of blocks
which are left to light up:</p><div class="patch-container" data-code-as-of-commit='import pytch


blocks_left = 0


class Background(pytch.Stage):
    Backdrops = ["background.png"]


class Block(pytch.Sprite):
    Costumes = ["block-unlit.png", "block-lit.png"]

    @pytch.when_green_flag_clicked
    def create_pyramid(self):
        for r in range(7):
            for b in range(7 - r):
                block_x = -150 + (b * 56) + (r * 28)
                block_y = -145 + (r * 42)
                self.go_to_xy(block_x, block_y)
                self.pyramid_r = r
                self.pyramid_b = b
                pytch.create_clone_of(self)
        self.hide()
        pytch.broadcast("set-up-qbert")

    @pytch.when_I_receive("check-block")
    def check_whether_landed_on(self):
        qbert_r, qbert_b = Qbert.the_original().pyramid_coordinates()
        if self.pyramid_r == qbert_r and self.pyramid_b == qbert_b:
            if self.costume_name == "block-unlit":
                self.switch_costume("block-lit")
                global blocks_left
                blocks_left -= 1


class Qbert(pytch.Sprite):
    Costumes = ["qbert0.png", "qbert1.png", "qbert2.png", "qbert3.png"]

    @pytch.when_green_flag_clicked
    def start_hidden(self):
        self.hide()

    # This list must have exactly 14 entries.
    bounce = [6, 4, 2, 1, 0, 0, 0, 0, 0, 0, -1, -2, -4, -6]

    @pytch.when_I_receive("set-up-qbert")
    def go_to_starting_position(self):
        self.go_to_xy(-150 + 3 * 56, -145 + (6 * 42) + 28)
        self.switch_costume("qbert1")
        self.go_to_front_layer()
        self.show()
        self.jumping = False
        global blocks_left
        blocks_left = len(Block.all_clones())

    def pyramid_coordinates(self):
        y_on_stage = self.y_position
        pyramid_r = (y_on_stage + 145 - 28) / 42
        x_on_stage = self.x_position
        pyramid_b = (x_on_stage + 150 - pyramid_r * 28) / 56
        return (pyramid_r, pyramid_b)

    def jump(self, x_speed, y_speed, costume):
        if self.jumping:
            return
        self.jumping = True
        self.switch_costume(costume)
        for frame in range(14):
            self.change_x(x_speed)
            self.change_y(y_speed + self.bounce[frame])

        r, b = self.pyramid_coordinates()
        if r &lt; 0 or r &gt;= 7 or b &lt; 0 or b &gt;= (7 - r):
            pytch.broadcast("fall-off")
        else:
            pytch.broadcast_and_wait("check-block")
            self.say("%d left" % blocks_left)
            self.jumping = False

    @pytch.when_I_receive("fall-off")
    def disappear(self):
        for i in range(100, 10, -5):
            self.set_size(i / 100.0)
        self.hide()

    @pytch.when_key_pressed("ArrowUp")
    def jump_up(self):
        self.jump(2, 3, "qbert0")

    @pytch.when_key_pressed("ArrowDown")
    def jump_down(self):
        self.jump(-2, -3, "qbert2")

    @pytch.when_key_pressed("ArrowLeft")
    def jump_left(self):
        self.jump(-2, 3, "qbert3")

    @pytch.when_key_pressed("ArrowRight")
    def jump_right(self):
        self.jump(2, -3, "qbert1")
' data-slug="temporarily-say-blocks-left-count"><div class="patch"><table><tbody class="diff-unch"><tr><td class="linenum"><pre>75</pre></td><td class="linenum"><pre>75</pre></td><td><pre>            pytch.broadcast("fall-off")</pre></td></tr><tr><td class="linenum"><pre>76</pre></td><td class="linenum"><pre>76</pre></td><td><pre>        else:</pre></td></tr><tr><td class="linenum"><pre>77</pre></td><td class="linenum"><pre>77</pre></td><td><pre>            pytch.broadcast_and_wait("check-block")</pre></td></tr></tbody><tbody class="diff-add" data-added-text='            self.say("%d left" % blocks_left)
'><tr><td class="linenum"></td><td class="linenum"><pre>78</pre></td><td><pre>            self.say("%d left" % blocks_left)</pre></td></tr></tbody><tbody class="diff-unch"><tr><td class="linenum"><pre>78</pre></td><td class="linenum"><pre>79</pre></td><td><pre>            self.jumping = False</pre></td></tr><tr><td class="linenum"><pre>79</pre></td><td class="linenum"><pre>80</pre></td><td><pre></pre></td></tr><tr><td class="linenum"><pre>80</pre></td><td class="linenum"><pre>81</pre></td><td><pre>    @pytch.when_I_receive("fall-off")</pre></td></tr></tbody></table></div></div><p>If you run this now, it mostly works, except that when you land on the
very top block, the count drops by <em>two</em> instead of one.  What's
happening is that the <em>original</em> instance of <em>Block</em> is updating the
count (even though it's hidden), as well as the clone which was
created there.  We'll fix this by making the original <em>Block</em> think
it's in a nonsense position.  This isn't a very elegant way of solving
this problem, but it will work:</p><div class="patch-container" data-code-as-of-commit='import pytch


blocks_left = 0


class Background(pytch.Stage):
    Backdrops = ["background.png"]


class Block(pytch.Sprite):
    Costumes = ["block-unlit.png", "block-lit.png"]

    @pytch.when_green_flag_clicked
    def create_pyramid(self):
        for r in range(7):
            for b in range(7 - r):
                block_x = -150 + (b * 56) + (r * 28)
                block_y = -145 + (r * 42)
                self.go_to_xy(block_x, block_y)
                self.pyramid_r = r
                self.pyramid_b = b
                pytch.create_clone_of(self)
        self.hide()
        self.pyramid_r = -1
        self.pyramid_b = -1
        pytch.broadcast("set-up-qbert")

    @pytch.when_I_receive("check-block")
    def check_whether_landed_on(self):
        qbert_r, qbert_b = Qbert.the_original().pyramid_coordinates()
        if self.pyramid_r == qbert_r and self.pyramid_b == qbert_b:
            if self.costume_name == "block-unlit":
                self.switch_costume("block-lit")
                global blocks_left
                blocks_left -= 1


class Qbert(pytch.Sprite):
    Costumes = ["qbert0.png", "qbert1.png", "qbert2.png", "qbert3.png"]

    @pytch.when_green_flag_clicked
    def start_hidden(self):
        self.hide()

    # This list must have exactly 14 entries.
    bounce = [6, 4, 2, 1, 0, 0, 0, 0, 0, 0, -1, -2, -4, -6]

    @pytch.when_I_receive("set-up-qbert")
    def go_to_starting_position(self):
        self.go_to_xy(-150 + 3 * 56, -145 + (6 * 42) + 28)
        self.switch_costume("qbert1")
        self.go_to_front_layer()
        self.show()
        self.jumping = False
        global blocks_left
        blocks_left = len(Block.all_clones())

    def pyramid_coordinates(self):
        y_on_stage = self.y_position
        pyramid_r = (y_on_stage + 145 - 28) / 42
        x_on_stage = self.x_position
        pyramid_b = (x_on_stage + 150 - pyramid_r * 28) / 56
        return (pyramid_r, pyramid_b)

    def jump(self, x_speed, y_speed, costume):
        if self.jumping:
            return
        self.jumping = True
        self.switch_costume(costume)
        for frame in range(14):
            self.change_x(x_speed)
            self.change_y(y_speed + self.bounce[frame])

        r, b = self.pyramid_coordinates()
        if r &lt; 0 or r &gt;= 7 or b &lt; 0 or b &gt;= (7 - r):
            pytch.broadcast("fall-off")
        else:
            pytch.broadcast_and_wait("check-block")
            self.say("%d left" % blocks_left)
            self.jumping = False

    @pytch.when_I_receive("fall-off")
    def disappear(self):
        for i in range(100, 10, -5):
            self.set_size(i / 100.0)
        self.hide()

    @pytch.when_key_pressed("ArrowUp")
    def jump_up(self):
        self.jump(2, 3, "qbert0")

    @pytch.when_key_pressed("ArrowDown")
    def jump_down(self):
        self.jump(-2, -3, "qbert2")

    @pytch.when_key_pressed("ArrowLeft")
    def jump_left(self):
        self.jump(-2, 3, "qbert3")

    @pytch.when_key_pressed("ArrowRight")
    def jump_right(self):
        self.jump(2, -3, "qbert1")
' data-slug="set-original-Block-coords-to-invalid-values"><div class="patch"><table><tbody class="diff-unch"><tr><td class="linenum"><pre>22</pre></td><td class="linenum"><pre>22</pre></td><td><pre>                self.pyramid_b = b</pre></td></tr><tr><td class="linenum"><pre>23</pre></td><td class="linenum"><pre>23</pre></td><td><pre>                pytch.create_clone_of(self)</pre></td></tr><tr><td class="linenum"><pre>24</pre></td><td class="linenum"><pre>24</pre></td><td><pre>        self.hide()</pre></td></tr></tbody><tbody class="diff-add" data-added-text="        self.pyramid_r = -1
        self.pyramid_b = -1
"><tr><td class="linenum"></td><td class="linenum"><pre>25</pre></td><td><pre>        self.pyramid_r = -1</pre></td></tr><tr><td class="linenum"></td><td class="linenum"><pre>26</pre></td><td><pre>        self.pyramid_b = -1</pre></td></tr></tbody><tbody class="diff-unch"><tr><td class="linenum"><pre>25</pre></td><td class="linenum"><pre>27</pre></td><td><pre>        pytch.broadcast("set-up-qbert")</pre></td></tr><tr><td class="linenum"><pre>26</pre></td><td class="linenum"><pre>28</pre></td><td><pre></pre></td></tr><tr><td class="linenum"><pre>27</pre></td><td class="linenum"><pre>29</pre></td><td><pre>    @pytch.when_I_receive("check-block")</pre></td></tr></tbody></table></div></div><p>Once you're happy this is working, you can remove the diagnostic
speech bubble:</p><div class="patch-container" data-code-as-of-commit='import pytch


blocks_left = 0


class Background(pytch.Stage):
    Backdrops = ["background.png"]


class Block(pytch.Sprite):
    Costumes = ["block-unlit.png", "block-lit.png"]

    @pytch.when_green_flag_clicked
    def create_pyramid(self):
        for r in range(7):
            for b in range(7 - r):
                block_x = -150 + (b * 56) + (r * 28)
                block_y = -145 + (r * 42)
                self.go_to_xy(block_x, block_y)
                self.pyramid_r = r
                self.pyramid_b = b
                pytch.create_clone_of(self)
        self.hide()
        self.pyramid_r = -1
        self.pyramid_b = -1
        pytch.broadcast("set-up-qbert")

    @pytch.when_I_receive("check-block")
    def check_whether_landed_on(self):
        qbert_r, qbert_b = Qbert.the_original().pyramid_coordinates()
        if self.pyramid_r == qbert_r and self.pyramid_b == qbert_b:
            if self.costume_name == "block-unlit":
                self.switch_costume("block-lit")
                global blocks_left
                blocks_left -= 1


class Qbert(pytch.Sprite):
    Costumes = ["qbert0.png", "qbert1.png", "qbert2.png", "qbert3.png"]

    @pytch.when_green_flag_clicked
    def start_hidden(self):
        self.hide()

    # This list must have exactly 14 entries.
    bounce = [6, 4, 2, 1, 0, 0, 0, 0, 0, 0, -1, -2, -4, -6]

    @pytch.when_I_receive("set-up-qbert")
    def go_to_starting_position(self):
        self.go_to_xy(-150 + 3 * 56, -145 + (6 * 42) + 28)
        self.switch_costume("qbert1")
        self.go_to_front_layer()
        self.show()
        self.jumping = False
        global blocks_left
        blocks_left = len(Block.all_clones())

    def pyramid_coordinates(self):
        y_on_stage = self.y_position
        pyramid_r = (y_on_stage + 145 - 28) / 42
        x_on_stage = self.x_position
        pyramid_b = (x_on_stage + 150 - pyramid_r * 28) / 56
        return (pyramid_r, pyramid_b)

    def jump(self, x_speed, y_speed, costume):
        if self.jumping:
            return
        self.jumping = True
        self.switch_costume(costume)
        for frame in range(14):
            self.change_x(x_speed)
            self.change_y(y_speed + self.bounce[frame])

        r, b = self.pyramid_coordinates()
        if r &lt; 0 or r &gt;= 7 or b &lt; 0 or b &gt;= (7 - r):
            pytch.broadcast("fall-off")
        else:
            pytch.broadcast_and_wait("check-block")
            self.jumping = False

    @pytch.when_I_receive("fall-off")
    def disappear(self):
        for i in range(100, 10, -5):
            self.set_size(i / 100.0)
        self.hide()

    @pytch.when_key_pressed("ArrowUp")
    def jump_up(self):
        self.jump(2, 3, "qbert0")

    @pytch.when_key_pressed("ArrowDown")
    def jump_down(self):
        self.jump(-2, -3, "qbert2")

    @pytch.when_key_pressed("ArrowLeft")
    def jump_left(self):
        self.jump(-2, 3, "qbert3")

    @pytch.when_key_pressed("ArrowRight")
    def jump_right(self):
        self.jump(2, -3, "qbert1")
' data-slug="remove-blocks-left-diagnostic"><div class="patch"><table><tbody class="diff-unch"><tr><td class="linenum"><pre>77</pre></td><td class="linenum"><pre>77</pre></td><td><pre>            pytch.broadcast("fall-off")</pre></td></tr><tr><td class="linenum"><pre>78</pre></td><td class="linenum"><pre>78</pre></td><td><pre>        else:</pre></td></tr><tr><td class="linenum"><pre>79</pre></td><td class="linenum"><pre>79</pre></td><td><pre>            pytch.broadcast_and_wait("check-block")</pre></td></tr></tbody><tbody class="diff-del"><tr><td class="linenum"><pre>80</pre></td><td class="linenum"></td><td><pre>            self.say("%d left" % blocks_left)</pre></td></tr></tbody><tbody class="diff-unch"><tr><td class="linenum"><pre>81</pre></td><td class="linenum"><pre>80</pre></td><td><pre>            self.jumping = False</pre></td></tr><tr><td class="linenum"><pre>82</pre></td><td class="linenum"><pre>81</pre></td><td><pre></pre></td></tr><tr><td class="linenum"><pre>83</pre></td><td class="linenum"><pre>82</pre></td><td><pre>    @pytch.when_I_receive("fall-off")</pre></td></tr></tbody></table></div></div></div><div class="chapter-content"><h2>Winning the game!</h2><p>When Q*bert has lit up all the blocks, we want to congratulate the
player.  We'll do this with a sprite with a message as its costume:</p><div class="patch-container" data-code-as-of-commit='import pytch


blocks_left = 0


class Background(pytch.Stage):
    Backdrops = ["background.png"]


class LevelClearedText(pytch.Sprite):
    Costumes = ["level-cleared-text.png"]


class Block(pytch.Sprite):
    Costumes = ["block-unlit.png", "block-lit.png"]

    @pytch.when_green_flag_clicked
    def create_pyramid(self):
        for r in range(7):
            for b in range(7 - r):
                block_x = -150 + (b * 56) + (r * 28)
                block_y = -145 + (r * 42)
                self.go_to_xy(block_x, block_y)
                self.pyramid_r = r
                self.pyramid_b = b
                pytch.create_clone_of(self)
        self.hide()
        self.pyramid_r = -1
        self.pyramid_b = -1
        pytch.broadcast("set-up-qbert")

    @pytch.when_I_receive("check-block")
    def check_whether_landed_on(self):
        qbert_r, qbert_b = Qbert.the_original().pyramid_coordinates()
        if self.pyramid_r == qbert_r and self.pyramid_b == qbert_b:
            if self.costume_name == "block-unlit":
                self.switch_costume("block-lit")
                global blocks_left
                blocks_left -= 1


class Qbert(pytch.Sprite):
    Costumes = ["qbert0.png", "qbert1.png", "qbert2.png", "qbert3.png"]

    @pytch.when_green_flag_clicked
    def start_hidden(self):
        self.hide()

    # This list must have exactly 14 entries.
    bounce = [6, 4, 2, 1, 0, 0, 0, 0, 0, 0, -1, -2, -4, -6]

    @pytch.when_I_receive("set-up-qbert")
    def go_to_starting_position(self):
        self.go_to_xy(-150 + 3 * 56, -145 + (6 * 42) + 28)
        self.switch_costume("qbert1")
        self.go_to_front_layer()
        self.show()
        self.jumping = False
        global blocks_left
        blocks_left = len(Block.all_clones())

    def pyramid_coordinates(self):
        y_on_stage = self.y_position
        pyramid_r = (y_on_stage + 145 - 28) / 42
        x_on_stage = self.x_position
        pyramid_b = (x_on_stage + 150 - pyramid_r * 28) / 56
        return (pyramid_r, pyramid_b)

    def jump(self, x_speed, y_speed, costume):
        if self.jumping:
            return
        self.jumping = True
        self.switch_costume(costume)
        for frame in range(14):
            self.change_x(x_speed)
            self.change_y(y_speed + self.bounce[frame])

        r, b = self.pyramid_coordinates()
        if r &lt; 0 or r &gt;= 7 or b &lt; 0 or b &gt;= (7 - r):
            pytch.broadcast("fall-off")
        else:
            pytch.broadcast_and_wait("check-block")
            self.jumping = False

    @pytch.when_I_receive("fall-off")
    def disappear(self):
        for i in range(100, 10, -5):
            self.set_size(i / 100.0)
        self.hide()

    @pytch.when_key_pressed("ArrowUp")
    def jump_up(self):
        self.jump(2, 3, "qbert0")

    @pytch.when_key_pressed("ArrowDown")
    def jump_down(self):
        self.jump(-2, -3, "qbert2")

    @pytch.when_key_pressed("ArrowLeft")
    def jump_left(self):
        self.jump(-2, 3, "qbert3")

    @pytch.when_key_pressed("ArrowRight")
    def jump_right(self):
        self.jump(2, -3, "qbert1")
' data-slug="add-LevelClearedText-with-costume"><div class="patch"><table><tbody class="diff-unch"><tr><td class="linenum"><pre>8</pre></td><td class="linenum"><pre>8</pre></td><td><pre>    Backdrops = ["background.png"]</pre></td></tr><tr><td class="linenum"><pre>9</pre></td><td class="linenum"><pre>9</pre></td><td><pre></pre></td></tr><tr><td class="linenum"><pre>10</pre></td><td class="linenum"><pre>10</pre></td><td><pre></pre></td></tr></tbody><tbody class="diff-add" data-added-text='class LevelClearedText(pytch.Sprite):
    Costumes = ["level-cleared-text.png"]


'><tr><td class="linenum"></td><td class="linenum"><pre>11</pre></td><td><pre>class LevelClearedText(pytch.Sprite):</pre></td></tr><tr><td class="linenum"></td><td class="linenum"><pre>12</pre></td><td><pre>    Costumes = ["level-cleared-text.png"]</pre></td></tr><tr><td class="linenum"></td><td class="linenum"><pre>13</pre></td><td><pre></pre></td></tr><tr><td class="linenum"></td><td class="linenum"><pre>14</pre></td><td><pre></pre></td></tr></tbody><tbody class="diff-unch"><tr><td class="linenum"><pre>11</pre></td><td class="linenum"><pre>15</pre></td><td><pre>class Block(pytch.Sprite):</pre></td></tr><tr><td class="linenum"><pre>12</pre></td><td class="linenum"><pre>16</pre></td><td><pre>    Costumes = ["block-unlit.png", "block-lit.png"]</pre></td></tr><tr><td class="linenum"><pre>13</pre></td><td class="linenum"><pre>17</pre></td><td><pre></pre></td></tr></tbody></table></div></div><p>This Sprite should start off not shown:</p><div class="patch-container" data-code-as-of-commit='import pytch


blocks_left = 0


class Background(pytch.Stage):
    Backdrops = ["background.png"]


class LevelClearedText(pytch.Sprite):
    Costumes = ["level-cleared-text.png"]

    @pytch.when_green_flag_clicked
    def start_hidden(self):
        self.hide()


class Block(pytch.Sprite):
    Costumes = ["block-unlit.png", "block-lit.png"]

    @pytch.when_green_flag_clicked
    def create_pyramid(self):
        for r in range(7):
            for b in range(7 - r):
                block_x = -150 + (b * 56) + (r * 28)
                block_y = -145 + (r * 42)
                self.go_to_xy(block_x, block_y)
                self.pyramid_r = r
                self.pyramid_b = b
                pytch.create_clone_of(self)
        self.hide()
        self.pyramid_r = -1
        self.pyramid_b = -1
        pytch.broadcast("set-up-qbert")

    @pytch.when_I_receive("check-block")
    def check_whether_landed_on(self):
        qbert_r, qbert_b = Qbert.the_original().pyramid_coordinates()
        if self.pyramid_r == qbert_r and self.pyramid_b == qbert_b:
            if self.costume_name == "block-unlit":
                self.switch_costume("block-lit")
                global blocks_left
                blocks_left -= 1


class Qbert(pytch.Sprite):
    Costumes = ["qbert0.png", "qbert1.png", "qbert2.png", "qbert3.png"]

    @pytch.when_green_flag_clicked
    def start_hidden(self):
        self.hide()

    # This list must have exactly 14 entries.
    bounce = [6, 4, 2, 1, 0, 0, 0, 0, 0, 0, -1, -2, -4, -6]

    @pytch.when_I_receive("set-up-qbert")
    def go_to_starting_position(self):
        self.go_to_xy(-150 + 3 * 56, -145 + (6 * 42) + 28)
        self.switch_costume("qbert1")
        self.go_to_front_layer()
        self.show()
        self.jumping = False
        global blocks_left
        blocks_left = len(Block.all_clones())

    def pyramid_coordinates(self):
        y_on_stage = self.y_position
        pyramid_r = (y_on_stage + 145 - 28) / 42
        x_on_stage = self.x_position
        pyramid_b = (x_on_stage + 150 - pyramid_r * 28) / 56
        return (pyramid_r, pyramid_b)

    def jump(self, x_speed, y_speed, costume):
        if self.jumping:
            return
        self.jumping = True
        self.switch_costume(costume)
        for frame in range(14):
            self.change_x(x_speed)
            self.change_y(y_speed + self.bounce[frame])

        r, b = self.pyramid_coordinates()
        if r &lt; 0 or r &gt;= 7 or b &lt; 0 or b &gt;= (7 - r):
            pytch.broadcast("fall-off")
        else:
            pytch.broadcast_and_wait("check-block")
            self.jumping = False

    @pytch.when_I_receive("fall-off")
    def disappear(self):
        for i in range(100, 10, -5):
            self.set_size(i / 100.0)
        self.hide()

    @pytch.when_key_pressed("ArrowUp")
    def jump_up(self):
        self.jump(2, 3, "qbert0")

    @pytch.when_key_pressed("ArrowDown")
    def jump_down(self):
        self.jump(-2, -3, "qbert2")

    @pytch.when_key_pressed("ArrowLeft")
    def jump_left(self):
        self.jump(-2, 3, "qbert3")

    @pytch.when_key_pressed("ArrowRight")
    def jump_right(self):
        self.jump(2, -3, "qbert1")
' data-slug="start-LevelClearedText-not-shown"><div class="patch"><table><tbody class="diff-unch"><tr><td class="linenum"><pre>11</pre></td><td class="linenum"><pre>11</pre></td><td><pre>class LevelClearedText(pytch.Sprite):</pre></td></tr><tr><td class="linenum"><pre>12</pre></td><td class="linenum"><pre>12</pre></td><td><pre>    Costumes = ["level-cleared-text.png"]</pre></td></tr><tr><td class="linenum"><pre>13</pre></td><td class="linenum"><pre>13</pre></td><td><pre></pre></td></tr></tbody><tbody class="diff-add" data-added-text="    @pytch.when_green_flag_clicked
    def start_hidden(self):
        self.hide()

"><tr><td class="linenum"></td><td class="linenum"><pre>14</pre></td><td><pre>    @pytch.when_green_flag_clicked</pre></td></tr><tr><td class="linenum"></td><td class="linenum"><pre>15</pre></td><td><pre>    def start_hidden(self):</pre></td></tr><tr><td class="linenum"></td><td class="linenum"><pre>16</pre></td><td><pre>        self.hide()</pre></td></tr><tr><td class="linenum"></td><td class="linenum"><pre>17</pre></td><td><pre></pre></td></tr></tbody><tbody class="diff-unch"><tr><td class="linenum"><pre>14</pre></td><td class="linenum"><pre>18</pre></td><td><pre></pre></td></tr><tr><td class="linenum"><pre>15</pre></td><td class="linenum"><pre>19</pre></td><td><pre>class Block(pytch.Sprite):</pre></td></tr><tr><td class="linenum"><pre>16</pre></td><td class="linenum"><pre>20</pre></td><td><pre>    Costumes = ["block-unlit.png", "block-lit.png"]</pre></td></tr></tbody></table></div></div><p>And we'll define a simple method which puts the sprite in a useful
place and shows it when a message is broadcast:</p><div class="patch-container" data-code-as-of-commit='import pytch


blocks_left = 0


class Background(pytch.Stage):
    Backdrops = ["background.png"]


class LevelClearedText(pytch.Sprite):
    Costumes = ["level-cleared-text.png"]

    @pytch.when_green_flag_clicked
    def start_hidden(self):
        self.hide()

    @pytch.when_I_receive("level-cleared")
    def congratulate_player(self):
        self.go_to_xy(-150, 80)
        self.show()


class Block(pytch.Sprite):
    Costumes = ["block-unlit.png", "block-lit.png"]

    @pytch.when_green_flag_clicked
    def create_pyramid(self):
        for r in range(7):
            for b in range(7 - r):
                block_x = -150 + (b * 56) + (r * 28)
                block_y = -145 + (r * 42)
                self.go_to_xy(block_x, block_y)
                self.pyramid_r = r
                self.pyramid_b = b
                pytch.create_clone_of(self)
        self.hide()
        self.pyramid_r = -1
        self.pyramid_b = -1
        pytch.broadcast("set-up-qbert")

    @pytch.when_I_receive("check-block")
    def check_whether_landed_on(self):
        qbert_r, qbert_b = Qbert.the_original().pyramid_coordinates()
        if self.pyramid_r == qbert_r and self.pyramid_b == qbert_b:
            if self.costume_name == "block-unlit":
                self.switch_costume("block-lit")
                global blocks_left
                blocks_left -= 1


class Qbert(pytch.Sprite):
    Costumes = ["qbert0.png", "qbert1.png", "qbert2.png", "qbert3.png"]

    @pytch.when_green_flag_clicked
    def start_hidden(self):
        self.hide()

    # This list must have exactly 14 entries.
    bounce = [6, 4, 2, 1, 0, 0, 0, 0, 0, 0, -1, -2, -4, -6]

    @pytch.when_I_receive("set-up-qbert")
    def go_to_starting_position(self):
        self.go_to_xy(-150 + 3 * 56, -145 + (6 * 42) + 28)
        self.switch_costume("qbert1")
        self.go_to_front_layer()
        self.show()
        self.jumping = False
        global blocks_left
        blocks_left = len(Block.all_clones())

    def pyramid_coordinates(self):
        y_on_stage = self.y_position
        pyramid_r = (y_on_stage + 145 - 28) / 42
        x_on_stage = self.x_position
        pyramid_b = (x_on_stage + 150 - pyramid_r * 28) / 56
        return (pyramid_r, pyramid_b)

    def jump(self, x_speed, y_speed, costume):
        if self.jumping:
            return
        self.jumping = True
        self.switch_costume(costume)
        for frame in range(14):
            self.change_x(x_speed)
            self.change_y(y_speed + self.bounce[frame])

        r, b = self.pyramid_coordinates()
        if r &lt; 0 or r &gt;= 7 or b &lt; 0 or b &gt;= (7 - r):
            pytch.broadcast("fall-off")
        else:
            pytch.broadcast_and_wait("check-block")
            self.jumping = False

    @pytch.when_I_receive("fall-off")
    def disappear(self):
        for i in range(100, 10, -5):
            self.set_size(i / 100.0)
        self.hide()

    @pytch.when_key_pressed("ArrowUp")
    def jump_up(self):
        self.jump(2, 3, "qbert0")

    @pytch.when_key_pressed("ArrowDown")
    def jump_down(self):
        self.jump(-2, -3, "qbert2")

    @pytch.when_key_pressed("ArrowLeft")
    def jump_left(self):
        self.jump(-2, 3, "qbert3")

    @pytch.when_key_pressed("ArrowRight")
    def jump_right(self):
        self.jump(2, -3, "qbert1")
' data-slug="define-show-LevelClearedText-method"><div class="patch"><table><tbody class="diff-unch"><tr><td class="linenum"><pre>15</pre></td><td class="linenum"><pre>15</pre></td><td><pre>    def start_hidden(self):</pre></td></tr><tr><td class="linenum"><pre>16</pre></td><td class="linenum"><pre>16</pre></td><td><pre>        self.hide()</pre></td></tr><tr><td class="linenum"><pre>17</pre></td><td class="linenum"><pre>17</pre></td><td><pre></pre></td></tr></tbody><tbody class="diff-add" data-added-text='    @pytch.when_I_receive("level-cleared")
    def congratulate_player(self):
        self.go_to_xy(-150, 80)
        self.show()

'><tr><td class="linenum"></td><td class="linenum"><pre>18</pre></td><td><pre>    @pytch.when_I_receive("level-cleared")</pre></td></tr><tr><td class="linenum"></td><td class="linenum"><pre>19</pre></td><td><pre>    def congratulate_player(self):</pre></td></tr><tr><td class="linenum"></td><td class="linenum"><pre>20</pre></td><td><pre>        self.go_to_xy(-150, 80)</pre></td></tr><tr><td class="linenum"></td><td class="linenum"><pre>21</pre></td><td><pre>        self.show()</pre></td></tr><tr><td class="linenum"></td><td class="linenum"><pre>22</pre></td><td><pre></pre></td></tr></tbody><tbody class="diff-unch"><tr><td class="linenum"><pre>18</pre></td><td class="linenum"><pre>23</pre></td><td><pre></pre></td></tr><tr><td class="linenum"><pre>19</pre></td><td class="linenum"><pre>24</pre></td><td><pre>class Block(pytch.Sprite):</pre></td></tr><tr><td class="linenum"><pre>20</pre></td><td class="linenum"><pre>25</pre></td><td><pre>    Costumes = ["block-unlit.png", "block-lit.png"]</pre></td></tr></tbody></table></div></div><p>The only time the level might have been cleared is just after a new
block has been lit up, so at that point we'll check whether there are
zero blocks left, and send the <code>"level-cleared"</code> message if so:</p><div class="patch-container" data-code-as-of-commit='import pytch


blocks_left = 0


class Background(pytch.Stage):
    Backdrops = ["background.png"]


class LevelClearedText(pytch.Sprite):
    Costumes = ["level-cleared-text.png"]

    @pytch.when_green_flag_clicked
    def start_hidden(self):
        self.hide()

    @pytch.when_I_receive("level-cleared")
    def congratulate_player(self):
        self.go_to_xy(-150, 80)
        self.show()


class Block(pytch.Sprite):
    Costumes = ["block-unlit.png", "block-lit.png"]

    @pytch.when_green_flag_clicked
    def create_pyramid(self):
        for r in range(7):
            for b in range(7 - r):
                block_x = -150 + (b * 56) + (r * 28)
                block_y = -145 + (r * 42)
                self.go_to_xy(block_x, block_y)
                self.pyramid_r = r
                self.pyramid_b = b
                pytch.create_clone_of(self)
        self.hide()
        self.pyramid_r = -1
        self.pyramid_b = -1
        pytch.broadcast("set-up-qbert")

    @pytch.when_I_receive("check-block")
    def check_whether_landed_on(self):
        qbert_r, qbert_b = Qbert.the_original().pyramid_coordinates()
        if self.pyramid_r == qbert_r and self.pyramid_b == qbert_b:
            if self.costume_name == "block-unlit":
                self.switch_costume("block-lit")
                global blocks_left
                blocks_left -= 1
                if blocks_left == 0:
                    pytch.broadcast("level-cleared")


class Qbert(pytch.Sprite):
    Costumes = ["qbert0.png", "qbert1.png", "qbert2.png", "qbert3.png"]

    @pytch.when_green_flag_clicked
    def start_hidden(self):
        self.hide()

    # This list must have exactly 14 entries.
    bounce = [6, 4, 2, 1, 0, 0, 0, 0, 0, 0, -1, -2, -4, -6]

    @pytch.when_I_receive("set-up-qbert")
    def go_to_starting_position(self):
        self.go_to_xy(-150 + 3 * 56, -145 + (6 * 42) + 28)
        self.switch_costume("qbert1")
        self.go_to_front_layer()
        self.show()
        self.jumping = False
        global blocks_left
        blocks_left = len(Block.all_clones())

    def pyramid_coordinates(self):
        y_on_stage = self.y_position
        pyramid_r = (y_on_stage + 145 - 28) / 42
        x_on_stage = self.x_position
        pyramid_b = (x_on_stage + 150 - pyramid_r * 28) / 56
        return (pyramid_r, pyramid_b)

    def jump(self, x_speed, y_speed, costume):
        if self.jumping:
            return
        self.jumping = True
        self.switch_costume(costume)
        for frame in range(14):
            self.change_x(x_speed)
            self.change_y(y_speed + self.bounce[frame])

        r, b = self.pyramid_coordinates()
        if r &lt; 0 or r &gt;= 7 or b &lt; 0 or b &gt;= (7 - r):
            pytch.broadcast("fall-off")
        else:
            pytch.broadcast_and_wait("check-block")
            self.jumping = False

    @pytch.when_I_receive("fall-off")
    def disappear(self):
        for i in range(100, 10, -5):
            self.set_size(i / 100.0)
        self.hide()

    @pytch.when_key_pressed("ArrowUp")
    def jump_up(self):
        self.jump(2, 3, "qbert0")

    @pytch.when_key_pressed("ArrowDown")
    def jump_down(self):
        self.jump(-2, -3, "qbert2")

    @pytch.when_key_pressed("ArrowLeft")
    def jump_left(self):
        self.jump(-2, 3, "qbert3")

    @pytch.when_key_pressed("ArrowRight")
    def jump_right(self):
        self.jump(2, -3, "qbert1")
' data-slug="check-for-level-cleared-then-announce"><div class="patch"><table><tbody class="diff-unch"><tr><td class="linenum"><pre>47</pre></td><td class="linenum"><pre>47</pre></td><td><pre>                self.switch_costume("block-lit")</pre></td></tr><tr><td class="linenum"><pre>48</pre></td><td class="linenum"><pre>48</pre></td><td><pre>                global blocks_left</pre></td></tr><tr><td class="linenum"><pre>49</pre></td><td class="linenum"><pre>49</pre></td><td><pre>                blocks_left -= 1</pre></td></tr></tbody><tbody class="diff-add" data-added-text='                if blocks_left == 0:
                    pytch.broadcast("level-cleared")
'><tr><td class="linenum"></td><td class="linenum"><pre>50</pre></td><td><pre>                if blocks_left == 0:</pre></td></tr><tr><td class="linenum"></td><td class="linenum"><pre>51</pre></td><td><pre>                    pytch.broadcast("level-cleared")</pre></td></tr></tbody><tbody class="diff-unch"><tr><td class="linenum"><pre>50</pre></td><td class="linenum"><pre>52</pre></td><td><pre></pre></td></tr><tr><td class="linenum"><pre>51</pre></td><td class="linenum"><pre>53</pre></td><td><pre></pre></td></tr><tr><td class="linenum"><pre>52</pre></td><td class="linenum"><pre>54</pre></td><td><pre>class Qbert(pytch.Sprite):</pre></td></tr></tbody></table></div></div></div><div class="chapter-content"><h2>Making some noise</h2><p>The game is now playable, but to make it more interesting we'll
include some sounds.  We'll start with a victory sound, which will be
a trumpet fanfare.  The 'level cleared' announcement sprite is a good
one for this sound to belong to:</p><div class="patch-container" data-code-as-of-commit='import pytch


blocks_left = 0


class Background(pytch.Stage):
    Backdrops = ["background.png"]


class LevelClearedText(pytch.Sprite):
    Costumes = ["level-cleared-text.png"]
    Sounds = ["fanfare.mp3"]

    @pytch.when_green_flag_clicked
    def start_hidden(self):
        self.hide()

    @pytch.when_I_receive("level-cleared")
    def congratulate_player(self):
        self.go_to_xy(-150, 80)
        self.show()


class Block(pytch.Sprite):
    Costumes = ["block-unlit.png", "block-lit.png"]

    @pytch.when_green_flag_clicked
    def create_pyramid(self):
        for r in range(7):
            for b in range(7 - r):
                block_x = -150 + (b * 56) + (r * 28)
                block_y = -145 + (r * 42)
                self.go_to_xy(block_x, block_y)
                self.pyramid_r = r
                self.pyramid_b = b
                pytch.create_clone_of(self)
        self.hide()
        self.pyramid_r = -1
        self.pyramid_b = -1
        pytch.broadcast("set-up-qbert")

    @pytch.when_I_receive("check-block")
    def check_whether_landed_on(self):
        qbert_r, qbert_b = Qbert.the_original().pyramid_coordinates()
        if self.pyramid_r == qbert_r and self.pyramid_b == qbert_b:
            if self.costume_name == "block-unlit":
                self.switch_costume("block-lit")
                global blocks_left
                blocks_left -= 1
                if blocks_left == 0:
                    pytch.broadcast("level-cleared")


class Qbert(pytch.Sprite):
    Costumes = ["qbert0.png", "qbert1.png", "qbert2.png", "qbert3.png"]

    @pytch.when_green_flag_clicked
    def start_hidden(self):
        self.hide()

    # This list must have exactly 14 entries.
    bounce = [6, 4, 2, 1, 0, 0, 0, 0, 0, 0, -1, -2, -4, -6]

    @pytch.when_I_receive("set-up-qbert")
    def go_to_starting_position(self):
        self.go_to_xy(-150 + 3 * 56, -145 + (6 * 42) + 28)
        self.switch_costume("qbert1")
        self.go_to_front_layer()
        self.show()
        self.jumping = False
        global blocks_left
        blocks_left = len(Block.all_clones())

    def pyramid_coordinates(self):
        y_on_stage = self.y_position
        pyramid_r = (y_on_stage + 145 - 28) / 42
        x_on_stage = self.x_position
        pyramid_b = (x_on_stage + 150 - pyramid_r * 28) / 56
        return (pyramid_r, pyramid_b)

    def jump(self, x_speed, y_speed, costume):
        if self.jumping:
            return
        self.jumping = True
        self.switch_costume(costume)
        for frame in range(14):
            self.change_x(x_speed)
            self.change_y(y_speed + self.bounce[frame])

        r, b = self.pyramid_coordinates()
        if r &lt; 0 or r &gt;= 7 or b &lt; 0 or b &gt;= (7 - r):
            pytch.broadcast("fall-off")
        else:
            pytch.broadcast_and_wait("check-block")
            self.jumping = False

    @pytch.when_I_receive("fall-off")
    def disappear(self):
        for i in range(100, 10, -5):
            self.set_size(i / 100.0)
        self.hide()

    @pytch.when_key_pressed("ArrowUp")
    def jump_up(self):
        self.jump(2, 3, "qbert0")

    @pytch.when_key_pressed("ArrowDown")
    def jump_down(self):
        self.jump(-2, -3, "qbert2")

    @pytch.when_key_pressed("ArrowLeft")
    def jump_left(self):
        self.jump(-2, 3, "qbert3")

    @pytch.when_key_pressed("ArrowRight")
    def jump_right(self):
        self.jump(2, -3, "qbert1")
' data-slug="define-LevelClearedText-fanfare-sound"><div class="patch"><table><tbody class="diff-unch"><tr><td class="linenum"><pre>10</pre></td><td class="linenum"><pre>10</pre></td><td><pre></pre></td></tr><tr><td class="linenum"><pre>11</pre></td><td class="linenum"><pre>11</pre></td><td><pre>class LevelClearedText(pytch.Sprite):</pre></td></tr><tr><td class="linenum"><pre>12</pre></td><td class="linenum"><pre>12</pre></td><td><pre>    Costumes = ["level-cleared-text.png"]</pre></td></tr></tbody><tbody class="diff-add" data-added-text='    Sounds = ["fanfare.mp3"]
'><tr><td class="linenum"></td><td class="linenum"><pre>13</pre></td><td><pre>    Sounds = ["fanfare.mp3"]</pre></td></tr></tbody><tbody class="diff-unch"><tr><td class="linenum"><pre>13</pre></td><td class="linenum"><pre>14</pre></td><td><pre></pre></td></tr><tr><td class="linenum"><pre>14</pre></td><td class="linenum"><pre>15</pre></td><td><pre>    @pytch.when_green_flag_clicked</pre></td></tr><tr><td class="linenum"><pre>15</pre></td><td class="linenum"><pre>16</pre></td><td><pre>    def start_hidden(self):</pre></td></tr></tbody></table></div></div><p>And we want to play this sound at the same time as showing the
message:</p><div class="patch-container" data-code-as-of-commit='import pytch


blocks_left = 0


class Background(pytch.Stage):
    Backdrops = ["background.png"]


class LevelClearedText(pytch.Sprite):
    Costumes = ["level-cleared-text.png"]
    Sounds = ["fanfare.mp3"]

    @pytch.when_green_flag_clicked
    def start_hidden(self):
        self.hide()

    @pytch.when_I_receive("level-cleared")
    def congratulate_player(self):
        self.go_to_xy(-150, 80)
        self.show()
        self.start_sound("fanfare")


class Block(pytch.Sprite):
    Costumes = ["block-unlit.png", "block-lit.png"]

    @pytch.when_green_flag_clicked
    def create_pyramid(self):
        for r in range(7):
            for b in range(7 - r):
                block_x = -150 + (b * 56) + (r * 28)
                block_y = -145 + (r * 42)
                self.go_to_xy(block_x, block_y)
                self.pyramid_r = r
                self.pyramid_b = b
                pytch.create_clone_of(self)
        self.hide()
        self.pyramid_r = -1
        self.pyramid_b = -1
        pytch.broadcast("set-up-qbert")

    @pytch.when_I_receive("check-block")
    def check_whether_landed_on(self):
        qbert_r, qbert_b = Qbert.the_original().pyramid_coordinates()
        if self.pyramid_r == qbert_r and self.pyramid_b == qbert_b:
            if self.costume_name == "block-unlit":
                self.switch_costume("block-lit")
                global blocks_left
                blocks_left -= 1
                if blocks_left == 0:
                    pytch.broadcast("level-cleared")


class Qbert(pytch.Sprite):
    Costumes = ["qbert0.png", "qbert1.png", "qbert2.png", "qbert3.png"]

    @pytch.when_green_flag_clicked
    def start_hidden(self):
        self.hide()

    # This list must have exactly 14 entries.
    bounce = [6, 4, 2, 1, 0, 0, 0, 0, 0, 0, -1, -2, -4, -6]

    @pytch.when_I_receive("set-up-qbert")
    def go_to_starting_position(self):
        self.go_to_xy(-150 + 3 * 56, -145 + (6 * 42) + 28)
        self.switch_costume("qbert1")
        self.go_to_front_layer()
        self.show()
        self.jumping = False
        global blocks_left
        blocks_left = len(Block.all_clones())

    def pyramid_coordinates(self):
        y_on_stage = self.y_position
        pyramid_r = (y_on_stage + 145 - 28) / 42
        x_on_stage = self.x_position
        pyramid_b = (x_on_stage + 150 - pyramid_r * 28) / 56
        return (pyramid_r, pyramid_b)

    def jump(self, x_speed, y_speed, costume):
        if self.jumping:
            return
        self.jumping = True
        self.switch_costume(costume)
        for frame in range(14):
            self.change_x(x_speed)
            self.change_y(y_speed + self.bounce[frame])

        r, b = self.pyramid_coordinates()
        if r &lt; 0 or r &gt;= 7 or b &lt; 0 or b &gt;= (7 - r):
            pytch.broadcast("fall-off")
        else:
            pytch.broadcast_and_wait("check-block")
            self.jumping = False

    @pytch.when_I_receive("fall-off")
    def disappear(self):
        for i in range(100, 10, -5):
            self.set_size(i / 100.0)
        self.hide()

    @pytch.when_key_pressed("ArrowUp")
    def jump_up(self):
        self.jump(2, 3, "qbert0")

    @pytch.when_key_pressed("ArrowDown")
    def jump_down(self):
        self.jump(-2, -3, "qbert2")

    @pytch.when_key_pressed("ArrowLeft")
    def jump_left(self):
        self.jump(-2, 3, "qbert3")

    @pytch.when_key_pressed("ArrowRight")
    def jump_right(self):
        self.jump(2, -3, "qbert1")
' data-slug="play-fanfare-when-level-cleared"><div class="patch"><table><tbody class="diff-unch"><tr><td class="linenum"><pre>20</pre></td><td class="linenum"><pre>20</pre></td><td><pre>    def congratulate_player(self):</pre></td></tr><tr><td class="linenum"><pre>21</pre></td><td class="linenum"><pre>21</pre></td><td><pre>        self.go_to_xy(-150, 80)</pre></td></tr><tr><td class="linenum"><pre>22</pre></td><td class="linenum"><pre>22</pre></td><td><pre>        self.show()</pre></td></tr></tbody><tbody class="diff-add" data-added-text='        self.start_sound("fanfare")
'><tr><td class="linenum"></td><td class="linenum"><pre>23</pre></td><td><pre>        self.start_sound("fanfare")</pre></td></tr></tbody><tbody class="diff-unch"><tr><td class="linenum"><pre>23</pre></td><td class="linenum"><pre>24</pre></td><td><pre></pre></td></tr><tr><td class="linenum"><pre>24</pre></td><td class="linenum"><pre>25</pre></td><td><pre></pre></td></tr><tr><td class="linenum"><pre>25</pre></td><td class="linenum"><pre>26</pre></td><td><pre>class Block(pytch.Sprite):</pre></td></tr></tbody></table></div></div><p>The other sounds will belong to the <em>Block</em> sprite, and will play when
a block is landed on by Q*bert.  We'll make different noises
depending on whether the block was already lit up, so we declare two
sounds for the <em>Block</em> sprite:</p><div class="patch-container" data-code-as-of-commit='import pytch


blocks_left = 0


class Background(pytch.Stage):
    Backdrops = ["background.png"]


class LevelClearedText(pytch.Sprite):
    Costumes = ["level-cleared-text.png"]
    Sounds = ["fanfare.mp3"]

    @pytch.when_green_flag_clicked
    def start_hidden(self):
        self.hide()

    @pytch.when_I_receive("level-cleared")
    def congratulate_player(self):
        self.go_to_xy(-150, 80)
        self.show()
        self.start_sound("fanfare")


class Block(pytch.Sprite):
    Costumes = ["block-unlit.png", "block-lit.png"]
    Sounds = ["pop.mp3", "bell-ping.mp3"]

    @pytch.when_green_flag_clicked
    def create_pyramid(self):
        for r in range(7):
            for b in range(7 - r):
                block_x = -150 + (b * 56) + (r * 28)
                block_y = -145 + (r * 42)
                self.go_to_xy(block_x, block_y)
                self.pyramid_r = r
                self.pyramid_b = b
                pytch.create_clone_of(self)
        self.hide()
        self.pyramid_r = -1
        self.pyramid_b = -1
        pytch.broadcast("set-up-qbert")

    @pytch.when_I_receive("check-block")
    def check_whether_landed_on(self):
        qbert_r, qbert_b = Qbert.the_original().pyramid_coordinates()
        if self.pyramid_r == qbert_r and self.pyramid_b == qbert_b:
            if self.costume_name == "block-unlit":
                self.switch_costume("block-lit")
                global blocks_left
                blocks_left -= 1
                if blocks_left == 0:
                    pytch.broadcast("level-cleared")


class Qbert(pytch.Sprite):
    Costumes = ["qbert0.png", "qbert1.png", "qbert2.png", "qbert3.png"]

    @pytch.when_green_flag_clicked
    def start_hidden(self):
        self.hide()

    # This list must have exactly 14 entries.
    bounce = [6, 4, 2, 1, 0, 0, 0, 0, 0, 0, -1, -2, -4, -6]

    @pytch.when_I_receive("set-up-qbert")
    def go_to_starting_position(self):
        self.go_to_xy(-150 + 3 * 56, -145 + (6 * 42) + 28)
        self.switch_costume("qbert1")
        self.go_to_front_layer()
        self.show()
        self.jumping = False
        global blocks_left
        blocks_left = len(Block.all_clones())

    def pyramid_coordinates(self):
        y_on_stage = self.y_position
        pyramid_r = (y_on_stage + 145 - 28) / 42
        x_on_stage = self.x_position
        pyramid_b = (x_on_stage + 150 - pyramid_r * 28) / 56
        return (pyramid_r, pyramid_b)

    def jump(self, x_speed, y_speed, costume):
        if self.jumping:
            return
        self.jumping = True
        self.switch_costume(costume)
        for frame in range(14):
            self.change_x(x_speed)
            self.change_y(y_speed + self.bounce[frame])

        r, b = self.pyramid_coordinates()
        if r &lt; 0 or r &gt;= 7 or b &lt; 0 or b &gt;= (7 - r):
            pytch.broadcast("fall-off")
        else:
            pytch.broadcast_and_wait("check-block")
            self.jumping = False

    @pytch.when_I_receive("fall-off")
    def disappear(self):
        for i in range(100, 10, -5):
            self.set_size(i / 100.0)
        self.hide()

    @pytch.when_key_pressed("ArrowUp")
    def jump_up(self):
        self.jump(2, 3, "qbert0")

    @pytch.when_key_pressed("ArrowDown")
    def jump_down(self):
        self.jump(-2, -3, "qbert2")

    @pytch.when_key_pressed("ArrowLeft")
    def jump_left(self):
        self.jump(-2, 3, "qbert3")

    @pytch.when_key_pressed("ArrowRight")
    def jump_right(self):
        self.jump(2, -3, "qbert1")
' data-slug="define-pop-ping-sounds"><div class="patch"><table><tbody class="diff-unch"><tr><td class="linenum"><pre>25</pre></td><td class="linenum"><pre>25</pre></td><td><pre></pre></td></tr><tr><td class="linenum"><pre>26</pre></td><td class="linenum"><pre>26</pre></td><td><pre>class Block(pytch.Sprite):</pre></td></tr><tr><td class="linenum"><pre>27</pre></td><td class="linenum"><pre>27</pre></td><td><pre>    Costumes = ["block-unlit.png", "block-lit.png"]</pre></td></tr></tbody><tbody class="diff-add" data-added-text='    Sounds = ["pop.mp3", "bell-ping.mp3"]
'><tr><td class="linenum"></td><td class="linenum"><pre>28</pre></td><td><pre>    Sounds = ["pop.mp3", "bell-ping.mp3"]</pre></td></tr></tbody><tbody class="diff-unch"><tr><td class="linenum"><pre>28</pre></td><td class="linenum"><pre>29</pre></td><td><pre></pre></td></tr><tr><td class="linenum"><pre>29</pre></td><td class="linenum"><pre>30</pre></td><td><pre>    @pytch.when_green_flag_clicked</pre></td></tr><tr><td class="linenum"><pre>30</pre></td><td class="linenum"><pre>31</pre></td><td><pre>    def create_pyramid(self):</pre></td></tr></tbody></table></div></div><p>If a block is lighting up, then we'll play the bell:</p><div class="patch-container" data-code-as-of-commit='import pytch


blocks_left = 0


class Background(pytch.Stage):
    Backdrops = ["background.png"]


class LevelClearedText(pytch.Sprite):
    Costumes = ["level-cleared-text.png"]
    Sounds = ["fanfare.mp3"]

    @pytch.when_green_flag_clicked
    def start_hidden(self):
        self.hide()

    @pytch.when_I_receive("level-cleared")
    def congratulate_player(self):
        self.go_to_xy(-150, 80)
        self.show()
        self.start_sound("fanfare")


class Block(pytch.Sprite):
    Costumes = ["block-unlit.png", "block-lit.png"]
    Sounds = ["pop.mp3", "bell-ping.mp3"]

    @pytch.when_green_flag_clicked
    def create_pyramid(self):
        for r in range(7):
            for b in range(7 - r):
                block_x = -150 + (b * 56) + (r * 28)
                block_y = -145 + (r * 42)
                self.go_to_xy(block_x, block_y)
                self.pyramid_r = r
                self.pyramid_b = b
                pytch.create_clone_of(self)
        self.hide()
        self.pyramid_r = -1
        self.pyramid_b = -1
        pytch.broadcast("set-up-qbert")

    @pytch.when_I_receive("check-block")
    def check_whether_landed_on(self):
        qbert_r, qbert_b = Qbert.the_original().pyramid_coordinates()
        if self.pyramid_r == qbert_r and self.pyramid_b == qbert_b:
            if self.costume_name == "block-unlit":
                self.start_sound("bell-ping")
                self.switch_costume("block-lit")
                global blocks_left
                blocks_left -= 1
                if blocks_left == 0:
                    pytch.broadcast("level-cleared")


class Qbert(pytch.Sprite):
    Costumes = ["qbert0.png", "qbert1.png", "qbert2.png", "qbert3.png"]

    @pytch.when_green_flag_clicked
    def start_hidden(self):
        self.hide()

    # This list must have exactly 14 entries.
    bounce = [6, 4, 2, 1, 0, 0, 0, 0, 0, 0, -1, -2, -4, -6]

    @pytch.when_I_receive("set-up-qbert")
    def go_to_starting_position(self):
        self.go_to_xy(-150 + 3 * 56, -145 + (6 * 42) + 28)
        self.switch_costume("qbert1")
        self.go_to_front_layer()
        self.show()
        self.jumping = False
        global blocks_left
        blocks_left = len(Block.all_clones())

    def pyramid_coordinates(self):
        y_on_stage = self.y_position
        pyramid_r = (y_on_stage + 145 - 28) / 42
        x_on_stage = self.x_position
        pyramid_b = (x_on_stage + 150 - pyramid_r * 28) / 56
        return (pyramid_r, pyramid_b)

    def jump(self, x_speed, y_speed, costume):
        if self.jumping:
            return
        self.jumping = True
        self.switch_costume(costume)
        for frame in range(14):
            self.change_x(x_speed)
            self.change_y(y_speed + self.bounce[frame])

        r, b = self.pyramid_coordinates()
        if r &lt; 0 or r &gt;= 7 or b &lt; 0 or b &gt;= (7 - r):
            pytch.broadcast("fall-off")
        else:
            pytch.broadcast_and_wait("check-block")
            self.jumping = False

    @pytch.when_I_receive("fall-off")
    def disappear(self):
        for i in range(100, 10, -5):
            self.set_size(i / 100.0)
        self.hide()

    @pytch.when_key_pressed("ArrowUp")
    def jump_up(self):
        self.jump(2, 3, "qbert0")

    @pytch.when_key_pressed("ArrowDown")
    def jump_down(self):
        self.jump(-2, -3, "qbert2")

    @pytch.when_key_pressed("ArrowLeft")
    def jump_left(self):
        self.jump(-2, 3, "qbert3")

    @pytch.when_key_pressed("ArrowRight")
    def jump_right(self):
        self.jump(2, -3, "qbert1")
' data-slug="play-ping-for-newly-lit-up"><div class="patch"><table><tbody class="diff-unch"><tr><td class="linenum"><pre>47</pre></td><td class="linenum"><pre>47</pre></td><td><pre>        qbert_r, qbert_b = Qbert.the_original().pyramid_coordinates()</pre></td></tr><tr><td class="linenum"><pre>48</pre></td><td class="linenum"><pre>48</pre></td><td><pre>        if self.pyramid_r == qbert_r and self.pyramid_b == qbert_b:</pre></td></tr><tr><td class="linenum"><pre>49</pre></td><td class="linenum"><pre>49</pre></td><td><pre>            if self.costume_name == "block-unlit":</pre></td></tr></tbody><tbody class="diff-add" data-added-text='                self.start_sound("bell-ping")
'><tr><td class="linenum"></td><td class="linenum"><pre>50</pre></td><td><pre>                self.start_sound("bell-ping")</pre></td></tr></tbody><tbody class="diff-unch"><tr><td class="linenum"><pre>50</pre></td><td class="linenum"><pre>51</pre></td><td><pre>                self.switch_costume("block-lit")</pre></td></tr><tr><td class="linenum"><pre>51</pre></td><td class="linenum"><pre>52</pre></td><td><pre>                global blocks_left</pre></td></tr><tr><td class="linenum"><pre>52</pre></td><td class="linenum"><pre>53</pre></td><td><pre>                blocks_left -= 1</pre></td></tr></tbody></table></div></div><p>and if a block is already lit up, we'll play the pop.  We do this by
adding an <code>else</code> clause to the <code>if</code> test for whether the block is
newly lit:</p><div class="patch-container" data-code-as-of-commit='import pytch


blocks_left = 0


class Background(pytch.Stage):
    Backdrops = ["background.png"]


class LevelClearedText(pytch.Sprite):
    Costumes = ["level-cleared-text.png"]
    Sounds = ["fanfare.mp3"]

    @pytch.when_green_flag_clicked
    def start_hidden(self):
        self.hide()

    @pytch.when_I_receive("level-cleared")
    def congratulate_player(self):
        self.go_to_xy(-150, 80)
        self.show()
        self.start_sound("fanfare")


class Block(pytch.Sprite):
    Costumes = ["block-unlit.png", "block-lit.png"]
    Sounds = ["pop.mp3", "bell-ping.mp3"]

    @pytch.when_green_flag_clicked
    def create_pyramid(self):
        for r in range(7):
            for b in range(7 - r):
                block_x = -150 + (b * 56) + (r * 28)
                block_y = -145 + (r * 42)
                self.go_to_xy(block_x, block_y)
                self.pyramid_r = r
                self.pyramid_b = b
                pytch.create_clone_of(self)
        self.hide()
        self.pyramid_r = -1
        self.pyramid_b = -1
        pytch.broadcast("set-up-qbert")

    @pytch.when_I_receive("check-block")
    def check_whether_landed_on(self):
        qbert_r, qbert_b = Qbert.the_original().pyramid_coordinates()
        if self.pyramid_r == qbert_r and self.pyramid_b == qbert_b:
            if self.costume_name == "block-unlit":
                self.start_sound("bell-ping")
                self.switch_costume("block-lit")
                global blocks_left
                blocks_left -= 1
                if blocks_left == 0:
                    pytch.broadcast("level-cleared")
            else:
                self.start_sound("pop")


class Qbert(pytch.Sprite):
    Costumes = ["qbert0.png", "qbert1.png", "qbert2.png", "qbert3.png"]

    @pytch.when_green_flag_clicked
    def start_hidden(self):
        self.hide()

    # This list must have exactly 14 entries.
    bounce = [6, 4, 2, 1, 0, 0, 0, 0, 0, 0, -1, -2, -4, -6]

    @pytch.when_I_receive("set-up-qbert")
    def go_to_starting_position(self):
        self.go_to_xy(-150 + 3 * 56, -145 + (6 * 42) + 28)
        self.switch_costume("qbert1")
        self.go_to_front_layer()
        self.show()
        self.jumping = False
        global blocks_left
        blocks_left = len(Block.all_clones())

    def pyramid_coordinates(self):
        y_on_stage = self.y_position
        pyramid_r = (y_on_stage + 145 - 28) / 42
        x_on_stage = self.x_position
        pyramid_b = (x_on_stage + 150 - pyramid_r * 28) / 56
        return (pyramid_r, pyramid_b)

    def jump(self, x_speed, y_speed, costume):
        if self.jumping:
            return
        self.jumping = True
        self.switch_costume(costume)
        for frame in range(14):
            self.change_x(x_speed)
            self.change_y(y_speed + self.bounce[frame])

        r, b = self.pyramid_coordinates()
        if r &lt; 0 or r &gt;= 7 or b &lt; 0 or b &gt;= (7 - r):
            pytch.broadcast("fall-off")
        else:
            pytch.broadcast_and_wait("check-block")
            self.jumping = False

    @pytch.when_I_receive("fall-off")
    def disappear(self):
        for i in range(100, 10, -5):
            self.set_size(i / 100.0)
        self.hide()

    @pytch.when_key_pressed("ArrowUp")
    def jump_up(self):
        self.jump(2, 3, "qbert0")

    @pytch.when_key_pressed("ArrowDown")
    def jump_down(self):
        self.jump(-2, -3, "qbert2")

    @pytch.when_key_pressed("ArrowLeft")
    def jump_left(self):
        self.jump(-2, 3, "qbert3")

    @pytch.when_key_pressed("ArrowRight")
    def jump_right(self):
        self.jump(2, -3, "qbert1")
' data-slug="play-pop-for-already-lit-up"><div class="patch"><table><tbody class="diff-unch"><tr><td class="linenum"><pre>53</pre></td><td class="linenum"><pre>53</pre></td><td><pre>                blocks_left -= 1</pre></td></tr><tr><td class="linenum"><pre>54</pre></td><td class="linenum"><pre>54</pre></td><td><pre>                if blocks_left == 0:</pre></td></tr><tr><td class="linenum"><pre>55</pre></td><td class="linenum"><pre>55</pre></td><td><pre>                    pytch.broadcast("level-cleared")</pre></td></tr></tbody><tbody class="diff-add" data-added-text='            else:
                self.start_sound("pop")
'><tr><td class="linenum"></td><td class="linenum"><pre>56</pre></td><td><pre>            else:</pre></td></tr><tr><td class="linenum"></td><td class="linenum"><pre>57</pre></td><td><pre>                self.start_sound("pop")</pre></td></tr></tbody><tbody class="diff-unch"><tr><td class="linenum"><pre>56</pre></td><td class="linenum"><pre>58</pre></td><td><pre></pre></td></tr><tr><td class="linenum"><pre>57</pre></td><td class="linenum"><pre>59</pre></td><td><pre></pre></td></tr><tr><td class="linenum"><pre>58</pre></td><td class="linenum"><pre>60</pre></td><td><pre>class Qbert(pytch.Sprite):</pre></td></tr></tbody></table></div></div></div><div class="chapter-content"><h2>Add instructions</h2><p>To tell the player how to use our game, we'll add some instructions at
the top of our code.  We'll do this using a Python <em>comment</em>, which is
a part of your program meant just for human readers — Python ignores
it.  In Python, a line starting with the <code>#</code> character is a comment.
We'll add a short explanation of the aim of the game, and how you move
Q*bert, using two comment lines:</p><div class="patch-container" data-code-as-of-commit="# Turn all the blocks yellow by jumping with the arrow keys,
# but don't fall off the pyramid!

import pytch


blocks_left = 0


class Background(pytch.Stage):
    Backdrops = [&quot;background.png&quot;]


class LevelClearedText(pytch.Sprite):
    Costumes = [&quot;level-cleared-text.png&quot;]
    Sounds = [&quot;fanfare.mp3&quot;]

    @pytch.when_green_flag_clicked
    def start_hidden(self):
        self.hide()

    @pytch.when_I_receive(&quot;level-cleared&quot;)
    def congratulate_player(self):
        self.go_to_xy(-150, 80)
        self.show()
        self.start_sound(&quot;fanfare&quot;)


class Block(pytch.Sprite):
    Costumes = [&quot;block-unlit.png&quot;, &quot;block-lit.png&quot;]
    Sounds = [&quot;pop.mp3&quot;, &quot;bell-ping.mp3&quot;]

    @pytch.when_green_flag_clicked
    def create_pyramid(self):
        for r in range(7):
            for b in range(7 - r):
                block_x = -150 + (b * 56) + (r * 28)
                block_y = -145 + (r * 42)
                self.go_to_xy(block_x, block_y)
                self.pyramid_r = r
                self.pyramid_b = b
                pytch.create_clone_of(self)
        self.hide()
        self.pyramid_r = -1
        self.pyramid_b = -1
        pytch.broadcast(&quot;set-up-qbert&quot;)

    @pytch.when_I_receive(&quot;check-block&quot;)
    def check_whether_landed_on(self):
        qbert_r, qbert_b = Qbert.the_original().pyramid_coordinates()
        if self.pyramid_r == qbert_r and self.pyramid_b == qbert_b:
            if self.costume_name == &quot;block-unlit&quot;:
                self.start_sound(&quot;bell-ping&quot;)
                self.switch_costume(&quot;block-lit&quot;)
                global blocks_left
                blocks_left -= 1
                if blocks_left == 0:
                    pytch.broadcast(&quot;level-cleared&quot;)
            else:
                self.start_sound(&quot;pop&quot;)


class Qbert(pytch.Sprite):
    Costumes = [&quot;qbert0.png&quot;, &quot;qbert1.png&quot;, &quot;qbert2.png&quot;, &quot;qbert3.png&quot;]

    @pytch.when_green_flag_clicked
    def start_hidden(self):
        self.hide()

    # This list must have exactly 14 entries.
    bounce = [6, 4, 2, 1, 0, 0, 0, 0, 0, 0, -1, -2, -4, -6]

    @pytch.when_I_receive(&quot;set-up-qbert&quot;)
    def go_to_starting_position(self):
        self.go_to_xy(-150 + 3 * 56, -145 + (6 * 42) + 28)
        self.switch_costume(&quot;qbert1&quot;)
        self.go_to_front_layer()
        self.show()
        self.jumping = False
        global blocks_left
        blocks_left = len(Block.all_clones())

    def pyramid_coordinates(self):
        y_on_stage = self.y_position
        pyramid_r = (y_on_stage + 145 - 28) / 42
        x_on_stage = self.x_position
        pyramid_b = (x_on_stage + 150 - pyramid_r * 28) / 56
        return (pyramid_r, pyramid_b)

    def jump(self, x_speed, y_speed, costume):
        if self.jumping:
            return
        self.jumping = True
        self.switch_costume(costume)
        for frame in range(14):
            self.change_x(x_speed)
            self.change_y(y_speed + self.bounce[frame])

        r, b = self.pyramid_coordinates()
        if r &lt; 0 or r &gt;= 7 or b &lt; 0 or b &gt;= (7 - r):
            pytch.broadcast(&quot;fall-off&quot;)
        else:
            pytch.broadcast_and_wait(&quot;check-block&quot;)
            self.jumping = False

    @pytch.when_I_receive(&quot;fall-off&quot;)
    def disappear(self):
        for i in range(100, 10, -5):
            self.set_size(i / 100.0)
        self.hide()

    @pytch.when_key_pressed(&quot;ArrowUp&quot;)
    def jump_up(self):
        self.jump(2, 3, &quot;qbert0&quot;)

    @pytch.when_key_pressed(&quot;ArrowDown&quot;)
    def jump_down(self):
        self.jump(-2, -3, &quot;qbert2&quot;)

    @pytch.when_key_pressed(&quot;ArrowLeft&quot;)
    def jump_left(self):
        self.jump(-2, 3, &quot;qbert3&quot;)

    @pytch.when_key_pressed(&quot;ArrowRight&quot;)
    def jump_right(self):
        self.jump(2, -3, &quot;qbert1&quot;)
" data-slug="add-player-instructions"><div class="patch"><table><tbody class="diff-add" data-added-text="# Turn all the blocks yellow by jumping with the arrow keys,
# but don't fall off the pyramid!

"><tr><td class="linenum"></td><td class="linenum"><pre>1</pre></td><td><pre># Turn all the blocks yellow by jumping with the arrow keys,</pre></td></tr><tr><td class="linenum"></td><td class="linenum"><pre>2</pre></td><td><pre># but don't fall off the pyramid!</pre></td></tr><tr><td class="linenum"></td><td class="linenum"><pre>3</pre></td><td><pre></pre></td></tr></tbody><tbody class="diff-unch"><tr><td class="linenum"><pre>1</pre></td><td class="linenum"><pre>4</pre></td><td><pre>import pytch</pre></td></tr><tr><td class="linenum"><pre>2</pre></td><td class="linenum"><pre>5</pre></td><td><pre></pre></td></tr><tr><td class="linenum"><pre>3</pre></td><td class="linenum"><pre>6</pre></td><td><pre></pre></td></tr></tbody></table></div></div></div><div class="chapter-content"><h2>Challenges</h2><p>This is now a playable game, although quite easy once you get the hang
of it!  There's lots more you could do with it:</p><ul>
<li>The player can keep making Q*bert jump around the pyramid after
  clearing the level, which looks odd.  What's the best way to handle
  this?</li>
<li>When Q*bert falls off the pyramid, they just get smaller.  It would
  look better if they looked like they carried on falling, at an
  increasing speed.</li>
<li>Add enemies, like were in the original, such as bouncy balls which
  you have to avoid.</li>
<li>Make there be more than one level.  Different levels could have
  different colour schemes.</li>
<li>Add the safety discs of the original, which transport Q*bert back
  to the top of the pyramid.</li>
</ul></div><div class="chapter-content"><h2>Credits</h2><p>Many thanks to the Raspberry Pi Press for making the contents of their
<em>Wireframe</em> magazine available under a Creative Commons licence.  We
have used their code for inspiration, and also the images.</p><p>Many thanks to Freesound users <em>greenvwbeetle</em>, <em>Robinhood76</em>, and
<em>InspectorJ</em> for making their sound effects available under friendly
licences.</p><div class="asset-credits"><p class="credit-intro">For <code class="asset-filename">background.png</code> (used in the project):</p><div class="credits"><p>The image <a href="https://github.com/Wireframe-Magazine/Wireframe-42/blob/master/source-code-qbert/images/"><em>Background image for Q*bert
example</em></a>
is copyright Raspberry Pi Press, 2020.  We use it under the <a href="https://creativecommons.org/licenses/by-nc-sa/3.0/">Creative
Commons Attribution-NonCommercial-ShareAlike
3.0</a> licence.  We
have cropped it, and rearranged the content to fit the Pytch stage
dimensions.</p></div><p class="credit-intro">For <code class="asset-filename">block-lit.png</code>, <code class="asset-filename">block-unlit.png</code> (used in the project):</p><div class="credits"><p>The images <a href="https://github.com/Wireframe-Magazine/Wireframe-42/blob/master/source-code-qbert/images/"><em>Block images for Q*bert
example</em></a>
are copyright Raspberry Pi Press, 2020.  We use them under the
<a href="https://creativecommons.org/licenses/by-nc-sa/3.0/">Creative Commons Attribution-NonCommercial-ShareAlike
3.0</a> licence.  We
have resized them to 56×56 pixels, adjusting a few pixels slightly to
do so.</p></div><p class="credit-intro">For <code class="asset-filename">qbert0.png</code>, <code class="asset-filename">qbert1.png</code>, <code class="asset-filename">qbert2.png</code>, <code class="asset-filename">qbert3.png</code> (used in the project):</p><div class="credits"><p>The images <a href="https://github.com/Wireframe-Magazine/Wireframe-42/blob/master/source-code-qbert/images/"><em>Player character images for Q*bert
example</em></a>
are copyright Raspberry Pi Press, 2020.  We use them under the <a href="https://creativecommons.org/licenses/by-nc-sa/3.0/">Creative
Commons Attribution-NonCommercial-ShareAlike
3.0</a> licence.</p></div><p class="credit-intro">For <code class="asset-filename">level-cleared-text.png</code> (used in the project):</p><div class="credits"><p>This image was created by the Pytch team for this tutorial, and is
hereby placed into the <a href="https://creativecommons.org/share-your-work/public-domain/cc0/">public
domain</a>.</p></div><p class="credit-intro">For <code class="asset-filename">pop.mp3</code> (used in the project):</p><div class="credits"><p>The sound <a href="https://freesound.org/s/244655/"><em>A popping sound</em></a> was
placed into the <a href="https://creativecommons.org/share-your-work/public-domain/cc0/">public
domain</a>
by its creator, Freesound
user <a href="https://freesound.org/people/greenvwbeetle/"><em>greenvwbeetle</em></a>.
We have cropped it and applied a fade-out effect.</p></div><p class="credit-intro">For <code class="asset-filename">bell-ping.mp3</code> (used in the project):</p><div class="credits"><p>The sound <a href="https://freesound.org/s/411089/"><em>Metal candle damper being struck with a metal
mallet</em></a> is copyright Freesound user
<a href="https://freesound.org/people/InspectorJ/">InspectorJ</a>, 2017.  We use
it under the <a href="https://creativecommons.org/licenses/by/3.0/">Creative Commons Attribution
3.0</a> licence.  We have
cropped it and applied a fade-out effect.</p></div><p class="credit-intro">For <code class="asset-filename">fanfare.mp3</code> (used in the project):</p><div class="credits"><p>The sound <a href="https://freesound.org/s/534017/"><em>Trumpets brass fanfare for complete
level</em></a> is copyright Freesound user
<a href="https://freesound.org/people/Robinhood76/"><em>Robinhood76</em></a>, 2020.  We
use it under the <a href="https://creativecommons.org/licenses/by-nc/3.0/">Creative Commons Attribution-NonCommercial
3.0</a> licence.  We
have cropped it, sped it up to 150% of its original speed (thereby
also raising its pitch by a perfect fifth), and applied a fade-out
effect.</p></div><p class="credit-intro">For <code class="asset-filename">screenshot.png</code> (used in the tutorial text/summary):</p><div class="credits"><p>This image was created by the Pytch team for this tutorial.  To the
extent that it uses <a href="https://github.com/Wireframe-Magazine/Wireframe-42/blob/master/source-code-qbert/images/">elements from the Wireframe
original</a>,
it is copyright Raspberry Pi Press, 2020.  We use those elements under
the <a href="https://creativecommons.org/licenses/by-nc-sa/3.0/">Creative Commons Attribution-NonCommercial-ShareAlike
3.0</a> licence.</p></div></div></div></div>